home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / emulator / uae-0.000 / uae-0 / uae-0.6.0 / custom.c < prev    next >
C/C++ Source or Header  |  1996-06-17  |  96KB  |  3,453 lines

  1.  /*
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * Custom chip emulation
  5.   * 
  6.   * (c) 1995 Bernd Schmidt, Alessandro Bissacco
  7.   */
  8.  
  9. #include "sysconfig.h"
  10. #include "sysdeps.h"
  11.  
  12. #include <ctype.h>
  13. #include <assert.h>
  14.  
  15. #include "config.h"
  16. #include "options.h"
  17. #include "events.h"
  18. #include "memory.h"
  19. #include "custom.h"
  20. #include "cia.h"
  21. #include "disk.h"
  22. #include "blit.h"
  23. #include "xwin.h"
  24. #include "os.h"
  25. #include "keybuf.h"
  26.  
  27. #define DMA_AUD0      0x0001
  28. #define DMA_AUD1      0x0002
  29. #define DMA_AUD2      0x0004
  30. #define DMA_AUD3      0x0008
  31. #define DMA_DISK      0x0010
  32. #define DMA_SPRITE    0x0020
  33. #define DMA_BLITTER   0x0040
  34. #define DMA_COPPER    0x0080
  35. #define DMA_BITPLANE  0x0100
  36. #define DMA_BLITPRI   0x0400
  37.  
  38. #define MAX_PLANES 8
  39.  
  40. #define PIXEL_XPOS(HPOS) (((HPOS)*2 - 0x30)*(use_lores ? 1 : 2))
  41.  
  42. /* These are default values for mouse calibration.
  43.  * The first two are default values for mstepx and mstepy.
  44.  * The second line set the orizontal and vertical offset for amiga and X 
  45.  * pointer matching
  46.  */
  47.    
  48. #define defstepx (1<<16)
  49. #define defstepy (1<<16)
  50. #define defxoffs 0
  51. #define defyoffs 0
  52.     
  53. /* Values below define mouse auto calibration process.
  54.  * They are not critical, change them if you want.
  55.  * The most important is calweight, which sets mouse adjustement rate */ 
  56.  
  57. static const int docal = 60, xcaloff = 40, ycaloff = 20;
  58. static const int calweight = 3;
  59.  
  60. static int lastsampledmx, lastsampledmy;
  61.  
  62.  /*
  63.   * Events
  64.   */
  65.  
  66. unsigned long int cycles, nextevent, nextev_count, specialflags;
  67. int vpos;
  68. UWORD lof;
  69.  
  70. struct ev eventtab[ev_max];
  71.  
  72. int copper_active;
  73.  
  74. static const int dskdelay = 2; /* FIXME: ??? */
  75.  
  76.  /* 
  77.   * hardware register values that are visible/can be written to by someone
  78.   */
  79.  
  80. static UWORD cregs[256];
  81.  
  82. static UWORD dmacon,intena,intreq;
  83. UWORD adkcon; /* used by audio code */
  84.  
  85. static ULONG cop1lc,cop2lc,copcon;
  86.  
  87. /* Kludge. FIXME: How does sprite restart after vsync work? */
  88. static int spron[8];
  89. static CPTR sprpt[8];
  90.  
  91. static ULONG bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat,bpl7dat,bpl8dat;
  92. static WORD  bpl1mod,bpl2mod;
  93.  
  94. xcolnr acolors[64];
  95.  
  96. UWORD *r_bplpt[MAX_PLANES];
  97. static CPTR bplpt[MAX_PLANES];
  98.  
  99. /*static int blitcount[256];  blitter debug */
  100.  
  101. struct bplinfo {
  102. #if AGA_CHIPSET == 0
  103.     /* X86.S will break if this isn't at the beginning of the structure. */
  104.     UWORD color_regs[32];
  105. #else
  106.     ULONG color_regs[256];
  107. #endif
  108.     UWORD bplcon0,bplcon1,bplcon2,bplcon3,bplcon4;
  109.     UWORD diwstrt,diwstop,ddfstrt,ddfstop;
  110.  
  111.     UWORD sprdata[8], sprdatb[8], sprctl[8], sprpos[8];
  112.     int sprarmed[8];
  113. } bpl_info;
  114.  
  115. struct line_description
  116. {
  117.     int inborder;
  118.     xcolnr bordercol;
  119.     struct bplinfo bpl_info;
  120.     struct mem_notify_node *mnn;
  121.     CPTR bplpt[MAX_PLANES];
  122.     int linedata_valid;
  123. };
  124.  
  125. /* 50 words give you 800 horizontal pixels. An A500 can't do that, so it ought
  126.  * to be enough. */
  127. #define MAX_WORDS_PER_LINE 50
  128. static UWORD line_data[numscrlines * 2][MAX_PLANES][MAX_WORDS_PER_LINE];
  129. static struct line_description linedescr[numscrlines * 2];
  130.  
  131. static UWORD bltsize;
  132. static UWORD bltcon0,bltcon1;
  133. static ULONG bltapt,bltbpt,bltcpt,bltdpt,bltcnxlpt,bltdnxlpt;
  134.  
  135. static ULONG dskpt;
  136. static UWORD dsklen,dsksync;
  137.  
  138. static int joy0x, joy1x, joy0y, joy1y;
  139. int joy0button;
  140. UWORD joy0dir;
  141. static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl;
  142. static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs;
  143. static int sprvbfl;
  144.  
  145. static enum { normal_mouse, dont_care_mouse, follow_mouse } mousestate;
  146.  
  147.  /*
  148.   * "hidden" hardware registers
  149.   */
  150.  
  151. int dblpf_ind1[256], dblpf_ind2[256], dblpf_2nd1[256], dblpf_2nd2[256], dblpf_aga1[256], dblpf_aga2[256];
  152.  
  153. int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 };
  154.  
  155. static ULONG coplc;
  156. static UWORD copi1,copi2;
  157.  
  158. static enum {
  159.     COP_stop, COP_read, COP_wait, COP_move, COP_skip
  160. } copstate;
  161.  
  162. static UWORD oldvblts,blitlpos,blinea,blineb;
  163. static int blitline,blitfc,blitfill,blitife,blitdesc,blitsing;
  164. static int blitonedot,blitsign;
  165. static long int bltwait;
  166.  
  167. static struct bltinfo blt_info;
  168.  
  169. static int dsklength;
  170.  
  171. static enum {
  172.     BLT_done, BLT_init, BLT_read, BLT_work, BLT_write, BLT_next
  173. } bltstate;
  174.  
  175. int plffirstline,plflastline,plfstrt,plfstop,plflinelen;
  176. int diwfirstword,diwlastword;
  177. int plfpri[3];
  178.  
  179. int max_diwstop, prev_max_diwstop;
  180.  
  181. int dskdmaen; /* used in cia.c */
  182. static UWORD dskmfm,dskbyte,dsktime;
  183. static int dsksynced;
  184.  
  185. int bpldelay1, bpldelay2;
  186. int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplhires;
  187.  
  188. static int pfield_fullline,pfield_linedone;
  189. static int pfield_linedmaon;
  190. static int pfield_lastpart_hpos,last_sprite;
  191. static int slowline_nextpos, slowline_linepos, slowline_lasttoscr;
  192.  
  193. union {
  194.     /* Let's try to align this thing. */
  195.     double uupzuq;
  196.     long int cruxmedo;
  197.     unsigned char apixels[1000];
  198. } pixdata;
  199.  
  200. char spixels[1000]; /* for sprites */
  201. char spixstate[1000]; /* more sprites */
  202.  
  203. ULONG aga_linebuf[1000], *aga_lbufptr;
  204.  
  205. char *xlinebuffer;
  206. int next_lineno, linetoscreen, line_in_border;
  207.  
  208. /*
  209.  * Statistics
  210.  */
  211.  
  212. static unsigned long int msecs = 0, frametime = 0, timeframes = 0;
  213. static unsigned long int seconds_base;
  214. int bogusframe;
  215.  
  216. /*
  217.  * helper functions
  218.  */
  219.  
  220. static void pfield_doline_slow(int);
  221. static void pfield_doline(void);
  222. static void do_sprites(int, int);
  223. static void maybe_blit(void);
  224.  
  225. int inhibit_frame;
  226. static int framecnt = 0;
  227.  
  228. static __inline__ void count_frame(void)
  229. {
  230.     if (inhibit_frame) 
  231.         framecnt = 1;
  232.     else {
  233.     framecnt++;
  234.     if (framecnt >= framerate)
  235.             framecnt = 0;
  236.     }
  237. }
  238.  
  239. static __inline__ void setclr(UWORD *p, UWORD val)
  240. {
  241.     if (val & 0x8000) {
  242.     *p |= val & 0x7FFF;
  243.     } else {
  244.     *p &= ~val;
  245.     }
  246. }
  247.  
  248. int dmaen(UWORD dmamask)
  249. {
  250.     return (dmamask & dmacon) && (dmacon & 0x200);
  251. }
  252.  
  253. static __inline__ int current_hpos(void)
  254. {
  255.     return cycles - eventtab[ev_hsync].oldcycles;
  256. }
  257.  
  258. static void calcdiw(void)
  259. {
  260.     if (use_lores) {
  261.     diwfirstword = (bpl_info.diwstrt & 0xFF) - 0x30 - 1;
  262.     diwlastword  = (bpl_info.diwstop & 0xFF) + 0x100 - 0x30 - 1;
  263.     } else {
  264.     diwfirstword = (bpl_info.diwstrt & 0xFF) * 2 - 0x60 - 2;
  265.     diwlastword  = (bpl_info.diwstop & 0xFF) * 2 + 0x200 - 0x60 - 2;
  266.     }
  267.     if (diwfirstword < 0) diwfirstword = 0;
  268.     if (diwlastword > max_diwstop) max_diwstop = diwlastword;
  269.     
  270.     plffirstline = bpl_info.diwstrt >> 8;
  271.     plflastline = bpl_info.diwstop >> 8;
  272. #if 0
  273.     /* This happens far too often. */
  274.     if (plffirstline < minfirstline) {
  275.     fprintf(stderr, "Warning: Playfield begins before line %d!\n", minfirstline);
  276.     plffirstline = minfirstline;
  277.     }
  278. #endif
  279.     if ((plflastline & 0x80) == 0) plflastline |= 0x100;
  280. #if 0 /* Turrican does this */
  281.     if (plflastline > 313) {
  282.     fprintf(stderr, "Warning: Playfield out of range!\n");
  283.     plflastline = 313;
  284.     }
  285. #endif
  286.     plfstrt = bpl_info.ddfstrt;
  287.     plfstop = bpl_info.ddfstop;
  288.     if (plfstrt < 0x18) plfstrt = 0x18;
  289.     if (plfstop > 0xD8) plfstop = 0xD8;
  290.     if (plfstrt > plfstop) plfstrt = plfstop;
  291.     
  292.     /* 
  293.      * Prize question: What are the next lines supposed to be?
  294.      * I can't seem to get it right.
  295.      */
  296. #if 0
  297.     /* Pretty good guess, but wrong. */
  298.     plflinelen = (plfstop-plfstrt+15) & ~7;
  299.     plfstrt &= ~(bplhires ? 3 : 7);
  300.     plfstop &= ~(bplhires ? 3 : 7);
  301. #endif
  302.     /* This actually seems to be correct now... */
  303.     
  304.     /* ! If the masking operation is changed, the pfield_doline code could break
  305.      * on some systems (alignment) */
  306.     plfstrt &= ~3;
  307.     plfstop &= ~3;
  308.     plflinelen = (plfstop-plfstrt+15) & ~7;
  309. }
  310.  
  311. /*
  312.  * Screen update macros
  313.  */
  314. #define LINE_TO_SCR(NAME, TYPE) \
  315. static void NAME(int pix, int stoppos) \
  316. { \
  317.     TYPE *buf = (TYPE *)xlinebuffer; \
  318.  \
  319.     while (pix < diwfirstword && pix < stoppos) { \
  320.     *buf++ = acolors[0]; pix++; \
  321.     } \
  322.     if (bplham && bplplanecnt == 6) { \
  323.     /* HAM */ \
  324.     static UWORD lastcolor; \
  325.     if (pix <= diwfirstword) \
  326.         lastcolor = bpl_info.color_regs[0]; \
  327.     while (pix < diwlastword && pix < stoppos) { \
  328.         int pv = pixdata.apixels[pix]; \
  329.         switch(pv & 0x30) { \
  330.          case 0x00: lastcolor = bpl_info.color_regs[pv]; break; \
  331.          case 0x10: lastcolor &= 0xFF0; lastcolor |= (pv & 0xF); break; \
  332.          case 0x20: lastcolor &= 0x0FF; lastcolor |= (pv & 0xF) << 8; break; \
  333.          case 0x30: lastcolor &= 0xF0F; lastcolor |= (pv & 0xF) << 4; break; \
  334.         } \
  335.  \
  336.         if (spixstate[pix]) { \
  337.         *buf++ = acolors[spixels[pix]+16]; \
  338.         spixels[pix] = spixstate[pix] = 0; \
  339.         } else { \
  340.         *buf++ = xcolors[lastcolor]; \
  341.         } \
  342.         pix++; \
  343.     } \
  344.     } else { \
  345.     if (bpldualpf) { \
  346.         int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; \
  347.         int *lookup_no = bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1; \
  348.         /* Dual playfield */ \
  349.         while (pix < diwlastword && pix < stoppos) { \
  350.         int pixcol = pixdata.apixels[pix]; \
  351.         int plno = lookup_no[pixcol]; \
  352.         if (spixstate[pix]) { \
  353.             int compare = plfpri[plno]; \
  354.             if (plno == 0 || spixstate[pix] < compare) \
  355.              *buf++ = acolors[spixels[pix]+16]; \
  356.             else \
  357.              *buf++ = acolors[lookup[pixcol]]; \
  358.                    spixels[pix] = spixstate[pix] = 0; \
  359.         } else { \
  360.             *buf++ = acolors[lookup[pixcol]]; \
  361.         } \
  362.         pix++; \
  363.         } \
  364.     } else { \
  365.         while (pix < diwlastword && pix < stoppos) { \
  366.         ULONG pixcol = pixdata.apixels[pix]; \
  367.         if (spixstate[pix]) { \
  368.             if (pixcol == 0 || spixstate[pix] < plfpri[2]) \
  369.             *buf++ = acolors[spixels[pix]+16]; \
  370.             else \
  371.             *buf++ = acolors[pixcol]; \
  372.             spixels[pix] = spixstate[pix] = 0; \
  373.         } else { \
  374.             *buf++ = acolors[pixcol]; \
  375.         } \
  376.         pix++; \
  377.         } \
  378.     } \
  379.     } \
  380.     while (pix < stoppos) { \
  381.     pix++; \
  382.     *buf++ = acolors[0]; \
  383.     } \
  384.     xlinebuffer = (char *)buf; \
  385. }
  386.  
  387. /* WARNING: Not too much of this will work correctly yet. */
  388.  
  389. static void linetoscr_aga(int pix, int stoppos)
  390. {
  391.     ULONG *buf = aga_lbufptr;
  392.     int i;
  393.     int xor = (UBYTE)(bpl_info.bplcon4 >> 8);
  394.     for (i = 0; i < stoppos; i++)
  395.     pixdata.apixels[i] ^= xor;
  396.     
  397.     while (pix < diwfirstword && pix < stoppos) {
  398.     *buf++ = bpl_info.color_regs[0]; pix++;
  399.     }
  400.     if (bplham && bplplanecnt == 6) {
  401.     /* HAM 6 */
  402.     static UWORD lastcolor;
  403.     if (pix <= diwfirstword)
  404.         lastcolor = bpl_info.color_regs[0];
  405.     while (pix < diwlastword && pix < stoppos) {
  406.         int pv = pixdata.apixels[pix];
  407.         switch(pv & 0x30) {
  408.          case 0x00: lastcolor = bpl_info.color_regs[pv]; break;
  409.          case 0x10: lastcolor &= 0xF0F000; lastcolor |= (pv & 0xF0); break;
  410.          case 0x20: lastcolor &= 0x00F0F0; lastcolor |= (pv & 0xF0) << 16; break;
  411.          case 0x30: lastcolor &= 0xF000F0; lastcolor |= (pv & 0xF0) << 8; break;
  412.         }
  413.  
  414.         if (spixstate[pix]) {
  415.         *buf++ = acolors[spixels[pix]+16];
  416.         spixels[pix] = spixstate[pix] = 0;
  417.         } else {
  418.         *buf++ = lastcolor;
  419.         }
  420.         pix++;
  421.     }
  422.     } else if (bplham && bplplanecnt == 8) {
  423.     /* HAM 8 */
  424.     static ULONG lastcolor;
  425.     if (pix <= diwfirstword)
  426.         lastcolor = bpl_info.color_regs[0];
  427.     while (pix < diwlastword && pix < stoppos) {
  428.         int pv = pixdata.apixels[pix];
  429.         switch(pv & 0x3) {
  430.          case 0x0: lastcolor = bpl_info.color_regs[pv >> 2]; break;
  431.          case 0x1: lastcolor &= 0xFFFF03; lastcolor |= (pv & 0xFC); break;
  432.          case 0x2: lastcolor &= 0x03FFFF; lastcolor |= (pv & 0xFC) << 16; break;
  433.          case 0x3: lastcolor &= 0xFF03FF; lastcolor |= (pv & 0xFC) << 8; break;
  434.         }
  435.  
  436.         if (spixstate[pix]) {
  437.         *buf++ = acolors[spixels[pix]+16];
  438.         spixels[pix] = spixstate[pix] = 0;
  439.         } else {
  440.         *buf++ = lastcolor;
  441.         }
  442.         pix++;
  443.     }
  444.     } else if (bpldualpf) {
  445.     int *lookup = bpldualpfpri ? dblpf_aga2 : dblpf_aga1;
  446.     int *lookup_no = bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1;
  447.     /* Dual playfield */
  448.     while (pix < diwlastword && pix < stoppos) {
  449.         int pixcol = pixdata.apixels[pix];
  450.         int pfno = lookup_no[pixcol];
  451.         
  452.         if (spixstate[pix]) {
  453.         ULONG spix = spixels[pix];
  454.         spixels[pix] = spixstate[pix] = 0;
  455.         
  456.             *buf++ = acolors[spixels[pix]+16];
  457.         } else {
  458.         int val = lookup[pixdata.apixels[pix]];
  459.         if (pfno == 2) 
  460.             val += dblpfofs[(bpl_info.bplcon2 >> 10) & 7];
  461.         *buf++ = acolors[val];
  462.         }
  463.         pix++;
  464.     }
  465.     } else if (bplehb) {
  466.     while (pix < diwlastword && pix < stoppos) {
  467.             int pixcol = pixdata.apixels[pix];
  468.         if (spixstate[pix]) {
  469.         if (pixcol == 0 || spixstate[pix] < plfpri[2])
  470.             *buf++ = acolors[spixels[pix]+16];
  471.         else
  472.             *buf++ = bpl_info.color_regs[pixcol];
  473.         spixels[pix] = spixstate[pix] = 0;
  474.         } else {
  475.         *buf++ = bpl_info.color_regs[pixcol];
  476.         }
  477.         pix++;
  478.     }
  479.     } else {
  480.     while (pix < diwlastword && pix < stoppos) {
  481.         int pixcol = pixdata.apixels[pix];
  482.         if (spixstate[pix]) {
  483.         if (pixcol == 0 || spixstate[pix] < plfpri[2]) 
  484.             *buf++ = bpl_info.color_regs[spixels[pix]+16];
  485.         else
  486.             *buf++ = bpl_info.color_regs[pixcol];
  487.         spixels[pix] = spixstate[pix] = 0;
  488.         } else {
  489.         *buf++ = bpl_info.color_regs[pixcol];
  490.         }
  491.         pix++;
  492.     }
  493.     }
  494.     while (pix < stoppos) {
  495.     pix++;
  496.     *buf++ = acolors[0];
  497.     }
  498.     aga_lbufptr = buf;
  499. }
  500.  
  501. #define FILL_LINE(NAME, TYPE) \
  502. static void NAME(char *buf) \
  503. { \
  504.     TYPE *b = (TYPE *)buf; \
  505.     int i;\
  506.     int maxpos = use_lores ? 400 : 796; \
  507.     xcolnr col = acolors[0]; \
  508.     for (i = 0; i < maxpos; i++) \
  509.         *b++ = col; \
  510. }
  511.  
  512. /* The following routines provide support for 2bit displays.
  513.  * Though coded specifically for NeXTStation Mono's they
  514.  * shoud be generically useful.
  515.  */    
  516. #define NX_INITPIXEL     char bitOffset=8;\
  517.         *b=0;
  518. #define NX_SETPIXEL(col)\
  519.     {\
  520.         if(bitOffset==0)\
  521.             {\
  522.             b ++;\
  523.             bitOffset=6;\
  524.             *b = (col<<6);\
  525.             }\
  526.         else\
  527.             {\
  528.             bitOffset-=2;\
  529.             *b |= (col<<bitOffset);\
  530.             }\
  531.     }
  532. /* Special 2bit version for NeXTStep */
  533. static void pfield_linetoscr_2(int pix, int stoppos) 
  534.     char *b = (char *)xlinebuffer; 
  535.     NX_INITPIXEL 
  536.     while (pix < diwfirstword && pix < stoppos) { 
  537.     NX_SETPIXEL(acolors[0]); pix++; 
  538.     } 
  539.     
  540.     if (bplham && bplplanecnt == 6) { 
  541.     /* HAM */ 
  542.     static UWORD lastcolor; 
  543.     if (pix <= diwfirstword) 
  544.         lastcolor = bpl_info.color_regs[0]; 
  545.     while (pix < diwlastword && pix < stoppos) { 
  546.         int pv = pixdata.apixels[pix]; 
  547.         switch(pv & 0x30) { 
  548.          case 0x00: lastcolor = bpl_info.color_regs[pv]; break; 
  549.          case 0x10: lastcolor &= 0xFF0; lastcolor |= (pv & 0xF); break; 
  550.          case 0x20: lastcolor &= 0x0FF; lastcolor |= (pv & 0xF) << 8; break; 
  551.          case 0x30: lastcolor &= 0xF0F; lastcolor |= (pv & 0xF) << 4; break; 
  552.         } 
  553.  
  554.         if (spixstate[pix]) { 
  555.         NX_SETPIXEL(acolors[spixels[pix]+16]); 
  556.         spixels[pix] = spixstate[pix] = 0; 
  557.         } else { 
  558.         NX_SETPIXEL(xcolors[lastcolor]);
  559.         } 
  560.         pix++; 
  561.     } 
  562.     } else { 
  563.     if (bpldualpf) { 
  564.         int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; 
  565.         /* Dual playfield */ 
  566.         while (pix < diwlastword && pix < stoppos) { 
  567.         if (spixstate[pix]) { 
  568.             NX_SETPIXEL( acolors[spixels[pix]+16]); 
  569.             spixels[pix] = spixstate[pix] = 0; 
  570.         } else { 
  571.             NX_SETPIXEL( acolors[lookup[pixdata.apixels[pix]]]); 
  572.         } 
  573.         pix++; 
  574.         } 
  575.     } else { 
  576.         while (pix < diwlastword && pix < stoppos) { 
  577.         if (spixstate[pix]) { 
  578.             if (pixdata.apixels[pix] == 0 || spixstate[pix] < plfpri[2])
  579.             {
  580.             NX_SETPIXEL( acolors[spixels[pix]+16]); 
  581.             }
  582.             else 
  583.             {
  584.             NX_SETPIXEL( acolors[pixdata.apixels[pix]]); 
  585.             }
  586.             spixels[pix] = spixstate[pix] = 0; 
  587.         } else { 
  588.             NX_SETPIXEL( acolors[pixdata.apixels[pix]]); 
  589.         } 
  590.         pix++; 
  591.         } 
  592.     } 
  593.     } 
  594.     while (pix < stoppos) { 
  595.     pix++; 
  596.     NX_SETPIXEL( acolors[0]); 
  597.     } 
  598.     xlinebuffer = (char *)b; 
  599. }
  600. /* Special 2bit version for NeXTStep */
  601. static void fill_line_2(char *buf)
  602. {
  603.     char *b = (char *)buf;
  604.     int i;
  605.     NX_INITPIXEL    
  606.     for (i = 0; i < 796; i++)
  607.         {
  608.         NX_SETPIXEL(acolors[0]);
  609.         }
  610. }
  611.  
  612. /* Portability hazard ahead... */
  613. LINE_TO_SCR(pfield_linetoscr_8, char)
  614. LINE_TO_SCR(pfield_linetoscr_16, short)
  615. LINE_TO_SCR(pfield_linetoscr_32, int)
  616.  
  617. FILL_LINE(fill_line_8, char)
  618. FILL_LINE(fill_line_16, short)
  619. FILL_LINE(fill_line_32, int)
  620.  
  621. #define pfield_linetoscr_full2 pfield_linetoscr_2
  622. #define pfield_linetoscr_full8 pfield_linetoscr_8
  623. #define pfield_linetoscr_full16 pfield_linetoscr_16
  624. #define pfield_linetoscr_full32 pfield_linetoscr_32
  625.  
  626. #if defined(X86_ASSEMBLY)
  627. #undef pfield_linetoscr_full8
  628. #undef pfield_linetoscr_full16
  629. extern void pfield_linetoscr_full8(int, int) __asm__("pfield_linetoscr_full8");
  630. extern void pfield_linetoscr_full16(int, int) __asm__("pfield_linetoscr_full16");
  631. #endif
  632.  
  633. static __inline__ void fill_line(int y)
  634. {
  635.     switch (gfxvidinfo.pixbytes) {
  636.      case 0: fill_line_2(gfxvidinfo.bufmem + gfxvidinfo.rowbytes * y); break;
  637.      case 1: fill_line_8(gfxvidinfo.bufmem + gfxvidinfo.rowbytes * y); break;
  638.      case 2: fill_line_16(gfxvidinfo.bufmem + gfxvidinfo.rowbytes * y); break;
  639.      case 4: fill_line_32(gfxvidinfo.bufmem + gfxvidinfo.rowbytes * y); break;
  640.     }
  641. }
  642.  
  643. static void pfield_slow_linetoscr(int start, int stop)
  644. {
  645.     int factor = use_lores ? 1 : 2;
  646.     int oldstop = stop;
  647.     
  648.     start = PIXEL_XPOS(start);
  649.     if (start < 8*factor)
  650.     start = 8*factor;
  651.     stop = PIXEL_XPOS(stop);
  652.     if (stop > 406*factor)
  653.     stop = 406*factor;
  654.     
  655.     if (start >= stop)
  656.     return;
  657.     slowline_lasttoscr = oldstop;
  658.  
  659.     if (start == 8*factor && stop == 406*factor) {
  660.     switch (gfxvidinfo.pixbytes) {
  661.      case 0: pfield_linetoscr_full2 (start, stop); break;
  662.      case 1: pfield_linetoscr_full8 (start, stop); break;
  663.      case 2: pfield_linetoscr_full16 (start, stop); break;
  664.      case 4: pfield_linetoscr_full32 (start, stop); break;
  665.     }
  666.     } else {
  667.     switch (gfxvidinfo.pixbytes) {
  668.      case 0: pfield_linetoscr_2 (start, stop); break;
  669.      case 1: pfield_linetoscr_8 (start, stop); break;
  670.      case 2: pfield_linetoscr_16 (start, stop); break;
  671.      case 4: pfield_linetoscr_32 (start, stop); break;
  672.     }
  673.     }
  674. }
  675.  
  676. /*
  677.  * This function is called whenever a hardware register that controls the
  678.  * screen display is modified. Usually, this routine does nothing. But in
  679.  * some cases, e.g., when a color changes in mid-screen, as in copper-plasma
  680.  * effects, this function switches the update method from the fast full-line
  681.  * update to the much slower single-color-clock update.
  682.  */
  683. static void pfield_may_need_update(int colreg)
  684. {
  685.     int i;
  686.     
  687.     /* Ignore, if this happened before or after the DDF window */
  688.     if (framecnt != 0 || !pfield_linedmaon || current_hpos() <= plfstrt
  689.     || vpos < plffirstline || vpos < minfirstline || vpos >= plflastline)
  690.     {    
  691.         return;
  692.     }
  693.     /* 
  694.      * If a color reg was modified, it is only important if we are within
  695.      * the DIW.
  696.      */
  697.     if (PIXEL_XPOS(current_hpos()) <= diwfirstword && colreg)
  698.         return;
  699.  
  700.     /*
  701.      * If we are past the DDF window, me might as well draw the complete
  702.      * line now.
  703.      */
  704.     if (current_hpos() > plfstrt + plflinelen && pfield_fullline) {
  705.     if (!pfield_linedone)
  706.         pfield_doline();
  707.     pfield_linedone = 1;
  708.     return;
  709.     }
  710.         
  711.     do_sprites(vpos, current_hpos());
  712.     if (pfield_fullline) {
  713.     pfield_lastpart_hpos = 0;
  714.     memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
  715.     pfield_fullline = 0;
  716.     slowline_nextpos = -1;
  717.     slowline_linepos = 0;
  718.     slowline_lasttoscr = 0;
  719.     } else {    
  720.     assert(pfield_lastpart_hpos <= current_hpos());
  721.     }
  722.     for (i = pfield_lastpart_hpos; i < current_hpos(); i++) {
  723.     pfield_doline_slow(i);
  724.     }
  725.     if (colreg) {
  726.     pfield_slow_linetoscr(slowline_lasttoscr, current_hpos());
  727.     }
  728.     pfield_lastpart_hpos = current_hpos();
  729. }
  730.  
  731. /* Apparently, the DMA bit is tested by the hardware at some point,
  732.  * presumably at the ddfstart position, to determine whether it
  733.  * ought to draw the line.
  734.  * This is probably not completely correct, but should not matter
  735.  * very much.
  736.  */
  737. static void pfield_calclinedma(void)
  738. {
  739.     if (current_hpos() >= plfstrt)
  740.         return;
  741.     
  742.     pfield_linedmaon = dmaen(DMA_BITPLANE);
  743. }
  744.  
  745.  /* 
  746.   * register functions
  747.   */
  748.  
  749. static UWORD DMACONR(void)
  750. {
  751.     return (dmacon | (bltstate==BLT_done ? 0 : 0x4000)
  752.         | (blt_info.blitzero ? 0x2000 : 0));
  753. }
  754. static UWORD INTENAR(void) { return intena; }
  755. static UWORD INTREQR(void) { return intreq; }
  756. static UWORD ADKCONR(void) { return adkcon; }
  757. static UWORD VPOSR(void) 
  758. {
  759. #if AGA_CHIPSET == 1
  760.     return (vpos >> 8) | lof | 0x2300;
  761. #else
  762. #ifdef ECS_AGNUS
  763.     return (vpos >> 8) | lof | 0x2000;
  764. #else
  765.     return (vpos >> 8) | lof;
  766. #endif
  767. #endif
  768. }
  769. static void  VPOSW(UWORD v)  { lof = v & 0x8000; }
  770. static UWORD VHPOSR(void) { return (vpos << 8) | current_hpos(); } 
  771.  
  772. static void  COP1LCH(UWORD v) { cop1lc= (cop1lc & 0xffff) | ((ULONG)v << 16); }
  773. static void  COP1LCL(UWORD v) { cop1lc= (cop1lc & ~0xffff) | v; }
  774. static void  COP2LCH(UWORD v) { cop2lc= (cop2lc & 0xffff) | ((ULONG)v << 16); }
  775. static void  COP2LCL(UWORD v) { cop2lc= (cop2lc & ~0xffff) | v; }
  776.  
  777. static void  COPJMP1(UWORD a)
  778. {
  779.     coplc = cop1lc; copstate = COP_read; 
  780.     eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
  781.     eventtab[ev_copper].evtime = 4; events_schedule();
  782.     copper_active = 1;
  783. }
  784. static void  COPJMP2(UWORD a)
  785. {
  786.     coplc = cop2lc; copstate = COP_read; 
  787.     eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
  788.     eventtab[ev_copper].evtime = 4; events_schedule();
  789.     copper_active = 1;
  790. }
  791.  
  792. static void  DMACON(UWORD v) 
  793. {
  794.     UWORD oldcon = dmacon;
  795.     setclr(&dmacon,v); dmacon &= 0x1FFF;
  796.     pfield_calclinedma();
  797.     
  798.     /* FIXME? Maybe we need to think a bit more about the master DMA enable 
  799.      * bit in these cases. */
  800.     if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) { 
  801.     COPJMP1(0);
  802.     }
  803.     if ((dmacon & DMA_SPRITE) > (oldcon & DMA_SPRITE)) {
  804.     int i;
  805.     for (i = 0; i < 8; i++)
  806.         spron[i] = 1;
  807.     }
  808.     if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) {
  809.     static int count = 0;
  810.     if (!count) {
  811.         count = 1;
  812.         fprintf(stderr, "warning: Program is doing blitpri hacks.\n");
  813.     }
  814.     specialflags |= SPCFLAG_BLTNASTY;
  815.     }
  816.     if (copper_active && !eventtab[ev_copper].active) {
  817.     eventtab[ev_copper].active = 1;
  818.     eventtab[ev_copper].oldcycles = cycles;
  819.     eventtab[ev_copper].evtime = 1;
  820.     events_schedule();
  821.     }
  822. }
  823. static void  INTENA(UWORD v) { setclr(&intena,v); specialflags |= SPCFLAG_INT; }
  824. static void  INTREQ(UWORD v) { setclr(&intreq,v); specialflags |= SPCFLAG_INT; }
  825. static void  ADKCON(UWORD v) { setclr(&adkcon,v); }
  826.  
  827. static void  BPLPTH(UWORD v, int num) { bplpt[num] = (bplpt[num] & 0xffff) | ((ULONG)v << 16); }
  828. static void  BPLPTL(UWORD v, int num) { bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xFFFE); }
  829.  
  830. /*
  831.  * I've seen the listing of an example program that changes 
  832.  * from lo- to hires while a line is being drawn. That's
  833.  * awful, but we want to emulate it.
  834.  */
  835. static void  BPLCON0(UWORD v) 
  836. {
  837.     if (bpl_info.bplcon0 == v)
  838.     return;
  839.     pfield_may_need_update(0);
  840.     bpl_info.bplcon0 = v;
  841.     bplhires = (v & 0x8000) == 0x8000;
  842.     bplplanecnt = (v & 0x7000) >> 12;
  843.     bplham = (v & 0x800) == 0x800;
  844.     bpldualpf = (v & 0x400) == 0x400;
  845.     bplehb = (v & 0xFDC0) == 0x6000 && !(bpl_info.bplcon2 & 0x200); /* see below */
  846.     calcdiw(); /* This should go away. */
  847. }
  848. static void  BPLCON1(UWORD v) 
  849. {
  850.     if (bpl_info.bplcon1 == v)
  851.     return;
  852.     pfield_may_need_update(0);
  853.     bpl_info.bplcon1 = v; 
  854.     bpldelay1 = v & 0xF; 
  855.     bpldelay2 = (v >> 4) & 0xF; 
  856. }
  857. static void  BPLCON2(UWORD v) 
  858. {
  859.     if (bpl_info.bplcon2 == v)
  860.     return;
  861.     pfield_may_need_update(0); 
  862.     bpl_info.bplcon2 = v;
  863.     bpldualpfpri = (v & 0x40) == 0x40;
  864.     plfpri[1] = 1 << 2*(v & 7);
  865.     plfpri[2] = 1 << 2*((v>>3) & 7);
  866.     bplehb = (bpl_info.bplcon0 & 0xFDC0) == 0x6000 && !(v & 0x200); /* see above */
  867. }
  868. static void  BPLCON3(UWORD v) 
  869. {
  870.     if (bpl_info.bplcon3 == v)
  871.     return;
  872.     pfield_may_need_update(0); 
  873.     bpl_info.bplcon3 = v; 
  874. }
  875. static void  BPLCON4(UWORD v) 
  876. {
  877.     if (bpl_info.bplcon4 == v)
  878.     return;
  879.     pfield_may_need_update(0); 
  880.     bpl_info.bplcon4 = v; 
  881. }
  882.  
  883. static void  BPL1MOD(UWORD v)
  884. {
  885.     v &= ~1;
  886.     if (bpl1mod == v)
  887.     return;
  888.     pfield_may_need_update(0); 
  889.     bpl1mod = v;
  890. }
  891. static void  BPL2MOD(UWORD v)
  892.     v &= ~1;
  893.     if (bpl2mod == v)
  894.     return;
  895.     pfield_may_need_update(0); 
  896.     bpl2mod = v;
  897. }
  898.  
  899. static void  BPL1DAT(UWORD v) { bpl1dat = v; }
  900. static void  BPL2DAT(UWORD v) { bpl2dat = v; }
  901. static void  BPL3DAT(UWORD v) { bpl3dat = v; }
  902. static void  BPL4DAT(UWORD v) { bpl4dat = v; }
  903. static void  BPL5DAT(UWORD v) { bpl5dat = v; }
  904. static void  BPL6DAT(UWORD v) { bpl6dat = v; }
  905.  
  906. /* We call pfield_may_need_update() from here. Actually, 
  907.  * I have no idea what happens if someone changes ddf or
  908.  * diw mid-line, and I don't really want to know. I doubt
  909.  * that this sort of thing was ever used to create a
  910.  * useful effect.
  911.  */
  912. static void  DIWSTRT(UWORD v) 
  913. {
  914.     if (bpl_info.diwstrt == v)
  915.     return;
  916.     pfield_may_need_update(0);
  917.     bpl_info.diwstrt = v; 
  918.     calcdiw();
  919. }
  920. static void  DIWSTOP(UWORD v)
  921. {
  922.     if (bpl_info.diwstop == v)
  923.     return;
  924.     pfield_may_need_update(0);
  925.     bpl_info.diwstop = v; 
  926.     calcdiw();
  927. }
  928. static void  DDFSTRT(UWORD v)
  929.     if (bpl_info.ddfstrt == v)
  930.     return;
  931.     pfield_may_need_update(0);
  932.     bpl_info.ddfstrt = v; 
  933.     calcdiw();
  934. }
  935. static void  DDFSTOP(UWORD v) 
  936.     if (bpl_info.ddfstop == v)
  937.     return;
  938.     pfield_may_need_update(0); 
  939.     bpl_info.ddfstop = v;
  940.     calcdiw();
  941. }
  942.  
  943. static void  BLTADAT(UWORD v) 
  944. {
  945.     maybe_blit(); 
  946.     blt_info.bltadat = v; 
  947. }
  948. static void  BLTBDAT(UWORD v)
  949. {
  950.     maybe_blit(); 
  951.     blt_info.bltbdat = v; 
  952. }
  953. static void  BLTCDAT(UWORD v) { maybe_blit(); blt_info.bltcdat = v; }
  954.  
  955. static void  BLTAMOD(UWORD v) { maybe_blit(); blt_info.bltamod = v & 0xFFFE; }
  956. static void  BLTBMOD(UWORD v) { maybe_blit(); blt_info.bltbmod = v & 0xFFFE; }
  957. static void  BLTCMOD(UWORD v) { maybe_blit(); blt_info.bltcmod = v & 0xFFFE; }
  958. static void  BLTDMOD(UWORD v) { maybe_blit(); blt_info.bltdmod = v & 0xFFFE; }
  959.  
  960. static void  BLTCON0(UWORD v) { maybe_blit(); bltcon0 = v; }
  961. /* The next category is "Most useless hardware register". 
  962.  * And the winner is... */
  963. static void  BLTCON0L(UWORD v) { maybe_blit(); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); }
  964. static void  BLTCON1(UWORD v) { maybe_blit(); bltcon1 = v; }
  965.  
  966. static void  BLTAFWM(UWORD v) { maybe_blit(); blt_info.bltafwm = v; }
  967. static void  BLTALWM(UWORD v) { maybe_blit(); blt_info.bltalwm = v; }
  968.  
  969. static void  BLTAPTH(UWORD v) { maybe_blit(); bltapt= (bltapt & 0xffff) | ((ULONG)v << 16); }
  970. static void  BLTAPTL(UWORD v) { maybe_blit(); bltapt= (bltapt & ~0xffff) | (v & 0xFFFE); }
  971. static void  BLTBPTH(UWORD v) { maybe_blit(); bltbpt= (bltbpt & 0xffff) | ((ULONG)v << 16); }
  972. static void  BLTBPTL(UWORD v) { maybe_blit(); bltbpt= (bltbpt & ~0xffff) | (v & 0xFFFE); }
  973. static void  BLTCPTH(UWORD v) { maybe_blit(); bltcpt= (bltcpt & 0xffff) | ((ULONG)v << 16); }
  974. static void  BLTCPTL(UWORD v) { maybe_blit(); bltcpt= (bltcpt & ~0xffff) | (v & 0xFFFE); }
  975. static void  BLTDPTH(UWORD v) { maybe_blit(); bltdpt= (bltdpt & 0xffff) | ((ULONG)v << 16); }
  976. static void  BLTDPTL(UWORD v) { maybe_blit(); bltdpt= (bltdpt & ~0xffff) | (v & 0xFFFE); }
  977. static void  BLTSIZE(UWORD v) 
  978. {
  979.     bltsize = v;
  980.     
  981.     maybe_blit(); 
  982.  
  983.     blt_info.vblitsize = bltsize >> 6;
  984.     blt_info.hblitsize = bltsize & 0x3F;
  985.     if (!blt_info.vblitsize) blt_info.vblitsize = 1024;
  986.     if (!blt_info.hblitsize) blt_info.hblitsize = 64;
  987.     
  988.     bltstate = BLT_init; 
  989.     specialflags |= SPCFLAG_BLIT; 
  990. }
  991. static void BLTSIZV(UWORD v) 
  992. {
  993.     maybe_blit(); 
  994.     oldvblts = v & 0x7FFF;
  995. }
  996. static void BLTSIZH(UWORD v) 
  997. {
  998.     maybe_blit(); 
  999.     blt_info.hblitsize = v & 0x7FF;
  1000.     blt_info.vblitsize = oldvblts;
  1001.     if (!blt_info.vblitsize) blt_info.vblitsize = 32768;
  1002.     if (!blt_info.hblitsize) blt_info.hblitsize = 0x800;
  1003.     bltstate = BLT_init; 
  1004.     specialflags |= SPCFLAG_BLIT;
  1005. }
  1006. static void  SPRxCTL_1(UWORD v, int num)
  1007. {
  1008.     bpl_info.sprctl[num] = v;
  1009.     bpl_info.sprarmed[num] = 0;
  1010.     if (bpl_info.sprpos[num] == 0 && v == 0)
  1011.     spron[num] = 0;
  1012.     else
  1013.     spron[num] |= 2;
  1014. }
  1015. static void  SPRxPOS_1(UWORD v, int num) 
  1016. {
  1017.     bpl_info.sprpos[num] = v; 
  1018. }
  1019. static void  SPRxDATA_1(UWORD v, int num)
  1020. {
  1021.     bpl_info.sprdata[num] = v;
  1022.     bpl_info.sprarmed[num] = 1; 
  1023. }
  1024. static void  SPRxDATB_1(UWORD v, int num) 
  1025. {
  1026.     bpl_info.sprdatb[num] = v;
  1027. }
  1028. static void  SPRxCTL(UWORD v, int num) { pfield_may_need_update(0); SPRxCTL_1(v, num); }
  1029. static void  SPRxPOS(UWORD v, int num) { pfield_may_need_update(0); SPRxPOS_1(v, num); }
  1030. static void  SPRxDATA(UWORD v, int num){ pfield_may_need_update(0); SPRxDATA_1(v, num); }
  1031. static void  SPRxDATB(UWORD v, int num){ pfield_may_need_update(0); SPRxDATB_1(v, num); }
  1032. static void  SPRxPTH(UWORD v, int num)
  1033. {
  1034.     sprpt[num] &= 0xffff; 
  1035.     sprpt[num] |= (ULONG)v << 16; 
  1036.     if (!spron[num]) spron[num] = 1; 
  1037. }
  1038. static void  SPRxPTL(UWORD v, int num)
  1039. {
  1040.     sprpt[num] &= ~0xffff; 
  1041.     sprpt[num] |= v; 
  1042.     if (!spron[num]) spron[num] = 1; 
  1043. }
  1044.  
  1045. static void  COLOR(UWORD v, int num)
  1046. {
  1047.     int r,g,b;
  1048.     int cr,cg,cb;
  1049.     int colreg;
  1050.     
  1051.     v &= 0xFFF;
  1052. #if AGA_CHIPSET == 1
  1053.     {
  1054.     ULONG cval;
  1055.     colreg = ((bpl_info.bplcon3 >> 13) & 7) * 32 + num;
  1056.     r = (v & 0xF00) >> 8;
  1057.     g = (v & 0xF0) >> 4;
  1058.     b = (v & 0xF) >> 0;
  1059.     cr = bpl_info.color_regs[colreg] >> 16;
  1060.     cg = (bpl_info.color_regs[colreg] >> 8) & 0xFF;
  1061.     cb = bpl_info.color_regs[colreg] & 0xFF;
  1062.  
  1063.     if (bpl_info.bplcon3 & 0x200) {
  1064.         cr = 0xF0; cr |= r;
  1065.         cg = 0xF0; cg |= g;
  1066.         cb = 0xF0; cb |= b;
  1067.     } else {
  1068.         cr = r + (r << 4);
  1069.         cg = g + (g << 4);
  1070.         cb = b + (b << 4);
  1071.     }
  1072.     cval = (cr << 16) | (cg << 8) | cb;
  1073.     if (cval == bpl_info.color_regs[colreg])
  1074.         return;
  1075.     bpl_info.color_regs[colreg] = cval;
  1076.     pfield_may_need_update(1);
  1077.     }
  1078. #else 
  1079.     {
  1080.     if (bpl_info.color_regs[num] == v)
  1081.         return;
  1082.     pfield_may_need_update(1);
  1083.     bpl_info.color_regs[num] = v;
  1084.     acolors[num] = xcolors[v];
  1085.     acolors[num+32] = xcolors[(v >> 1) & 0x777];
  1086.     }
  1087. #endif
  1088. }
  1089.  
  1090. static void  DSKSYNC(UWORD v) { dsksync = v; }
  1091. static void  DSKDAT(UWORD v) { dskmfm = v; }
  1092. static void  DSKPTH(UWORD v) { dskpt = (dskpt & 0xffff) | ((ULONG)v << 16); }
  1093. static void  DSKPTL(UWORD v) { dskpt = (dskpt & ~0xffff) | (v); }
  1094.  
  1095. static void  DSKLEN(UWORD v) 
  1096. {
  1097.     if (v & 0x8000) { dskdmaen++; } else { dskdmaen = 0; }
  1098.     dsktime = dskdelay; dsksynced = 0;
  1099.     dsklen = dsklength = v; dsklength &= 0x3fff;
  1100.     if (dskdmaen == 2 && dsksync != 0x4489 && (adkcon & 0x400)) {
  1101.     fprintf(stderr, "Non-standard sync: %04x len: %x\n", dsksync, dsklength);
  1102.     }
  1103.     if (dsklen & 0x4000) DISK_InitWrite();
  1104.     if (dskdmaen) specialflags |= SPCFLAG_DISK;
  1105. }
  1106.  
  1107. static UWORD DSKBYTR(void)
  1108. {
  1109.     UWORD v = (dsklen >> 1) & 0x6000;
  1110.     v |= dskbyte;
  1111.     dskbyte &= ~0x8000;
  1112.     if (dsksync == dskmfm) v |= 0x1000;
  1113.     return v;
  1114. }
  1115.  
  1116. static UWORD DSKDATR(void) { return dskmfm; }
  1117. static UWORD POTGOR(void)
  1118. {
  1119.     UWORD v = 0xFFFF;
  1120.     if (buttonstate[2])
  1121.     v &= 0xFBFF;
  1122.  
  1123.     if (buttonstate[1])
  1124.     v &= 0xFEFF;
  1125.     
  1126.     return v;
  1127. }
  1128. static UWORD POT0DAT(void)
  1129. {
  1130.     static UWORD cnt = 0;
  1131.     if (buttonstate[2])
  1132.     cnt = ((cnt + 1) & 0xFF) | (cnt & 0xFF00);
  1133.     if (buttonstate[1])
  1134.     cnt += 0x100;
  1135.     
  1136.     return cnt;
  1137. }
  1138. static UWORD JOY0DAT(void) { return joy0x + (joy0y << 8); }
  1139. static UWORD JOY1DAT(void)
  1140. {
  1141.     return joy0dir;
  1142. }
  1143. static void JOYTEST(UWORD v)
  1144. {
  1145.     joy0x = joy1x = v & 0xFC;
  1146.     joy0y = joy1y = (v >> 8) & 0xFC;    
  1147. }
  1148. static void AUD0LCH(UWORD v) { audlc[0] = (audlc[0] & 0xffff) | ((ULONG)v << 16); }
  1149. static void AUD0LCL(UWORD v) { audlc[0] = (audlc[0] & ~0xffff) | v; }
  1150. static void AUD1LCH(UWORD v) { audlc[1] = (audlc[1] & 0xffff) | ((ULONG)v << 16); }
  1151. static void AUD1LCL(UWORD v) { audlc[1] = (audlc[1] & ~0xffff) | v; }
  1152. static void AUD2LCH(UWORD v) { audlc[2] = (audlc[2] & 0xffff) | ((ULONG)v << 16); }
  1153. static void AUD2LCL(UWORD v) { audlc[2] = (audlc[2] & ~0xffff) | v; }
  1154. static void AUD3LCH(UWORD v) { audlc[3] = (audlc[3] & 0xffff) | ((ULONG)v << 16); }
  1155. static void AUD3LCL(UWORD v) { audlc[3] = (audlc[3] & ~0xffff) | v; }
  1156. static void AUD0PER(UWORD v) { audper[0] = v; }
  1157. static void AUD1PER(UWORD v) { audper[1] = v; }
  1158. static void AUD2PER(UWORD v) { audper[2] = v; }
  1159. static void AUD3PER(UWORD v) { audper[3] = v; }
  1160. static void AUD0VOL(UWORD v) { audvol[0] = v & 64 ? 63 : v & 63; }
  1161. static void AUD1VOL(UWORD v) { audvol[1] = v & 64 ? 63 : v & 63; }
  1162. static void AUD2VOL(UWORD v) { audvol[2] = v & 64 ? 63 : v & 63; }
  1163. static void AUD3VOL(UWORD v) { audvol[3] = v & 64 ? 63 : v & 63; }
  1164. static void AUD0LEN(UWORD v) { audlen[0] = v; }
  1165. static void AUD1LEN(UWORD v) { audlen[1] = v; }
  1166. static void AUD2LEN(UWORD v) { audlen[2] = v; }
  1167. static void AUD3LEN(UWORD v) { audlen[3] = v; }
  1168.  
  1169. static UWORD SERDATR(void) { return 0; }
  1170.  
  1171. static int copcomp(void)
  1172. {
  1173.     UWORD vp = vpos & (((copi2 >> 8) & 0x7F) | 0x80);
  1174.     UWORD hp = current_hpos() & (copi2 & 0xFE);
  1175.     UWORD vcmp = copi1 >> 8;
  1176.     UWORD hcmp = copi1 & 0xFE;
  1177.     return (vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000));
  1178. }
  1179.  
  1180. /*
  1181.  * Calculate the minimum number of cycles after which the
  1182.  * copper comparison becomes true. This is quite tricky. I hope it works.
  1183.  */
  1184. static int calc_copcomp_true(int currvpos, int currhpos)
  1185. {    
  1186.     UWORD vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  1187.     UWORD hp = currhpos & (copi2 & 0xFE);
  1188.     UWORD vcmp = copi1 >> 8;
  1189.     UWORD hcmp = copi1 & 0xFE;
  1190.     int copper_time_hpos;
  1191.     int cycleadd = maxhpos - currhpos;
  1192.     int coptime = 0;
  1193.  
  1194.     if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)))
  1195.         return 0;    
  1196.  
  1197.     try_again:
  1198.  
  1199.     while (vp < vcmp) {
  1200.     currvpos++;
  1201.     if (currvpos > maxvpos + 1)
  1202.         return -1;
  1203.     currhpos = 0;
  1204.     coptime += cycleadd;
  1205.     cycleadd = maxhpos;
  1206.     vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  1207.     }
  1208.     if (coptime > 0 && bplhires && bplplanecnt == 4)
  1209.     return coptime;
  1210.     copper_time_hpos = currhpos;
  1211.     hp = copper_time_hpos & (copi2 & 0xFE);
  1212.     if (!(vp > vcmp)) {    
  1213.     while (hp < hcmp-2) {
  1214.         currhpos++;
  1215.         /* Copper DMA is turned off in Hires 4 bitplane mode */
  1216.         if (!bplhires || bplplanecnt < 4 || !dmaen(DMA_BITPLANE)
  1217.         || currhpos < plfstrt-2 || currhpos > (plfstop+4))
  1218.         copper_time_hpos++;
  1219.         
  1220.         if (currhpos > maxhpos-4) {
  1221.         /* Now, what? There might be a good position on the
  1222.          * next line. But it can also be the FFFF FFFE
  1223.          * case.
  1224.          */
  1225.         currhpos = 0;
  1226.         currvpos++;
  1227.         vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  1228.         goto try_again;
  1229.         }
  1230.         coptime++;
  1231.         hp = copper_time_hpos & (copi2 & 0xFE);
  1232.     }
  1233.     }
  1234.     if (coptime == 0) /* waiting for the blitter */
  1235.         return 1;
  1236.  
  1237.     return coptime;
  1238. }
  1239.  
  1240. static void copper_read(void)
  1241. {
  1242.     if (dmaen(DMA_COPPER)){
  1243.     copi1 = chipmem_bank.wget(coplc); 
  1244.     copi2 = chipmem_bank.wget(coplc+2);
  1245.     coplc += 4;
  1246.     eventtab[ev_copper].oldcycles = cycles;
  1247.     eventtab[ev_copper].evtime = (copi1 & 1) ? (copi2 & 1) ? 10 : 8 : 4;
  1248.     copstate = (copi1 & 1) ? (copi2 & 1) ? COP_skip : COP_wait : COP_move;
  1249.     } else {
  1250.     copstate = COP_read;
  1251.     eventtab[ev_copper].active = 0;
  1252.     }
  1253. }
  1254.  
  1255. static void do_copper(void)
  1256. {    
  1257.     switch(copstate){
  1258.      case COP_read:
  1259.     copper_read();
  1260.     break;
  1261.      case COP_move:
  1262.     if (copi1 >= (copcon & 2 ? 0x40 : 0x80)) {
  1263.         custom_bank.wput(copi1,copi2);
  1264.         copper_read();
  1265.     } else {
  1266.         copstate = COP_stop;
  1267.         eventtab[ev_copper].active = 0;
  1268.         copper_active = 0;
  1269.     }
  1270.     break;
  1271.      case COP_skip:
  1272.     if (calc_copcomp_true(vpos, current_hpos()) == 0)
  1273.         coplc += 4;
  1274.     copper_read();
  1275.     break;
  1276.      case COP_wait: {        
  1277.      int coptime = calc_copcomp_true(vpos, current_hpos());
  1278.      if (coptime < 0) {
  1279.          copstate = COP_stop;
  1280.          eventtab[ev_copper].active = 0;
  1281.          copper_active = 0;
  1282.      } else {         
  1283.          if (!coptime)
  1284.               copper_read();
  1285.          else {
  1286.          eventtab[ev_copper].evtime = coptime;
  1287.          eventtab[ev_copper].oldcycles = cycles;
  1288.          }
  1289.      }
  1290.      break;
  1291.      }
  1292.      case COP_stop:
  1293.     eventtab[ev_copper].active = 0;
  1294.     copper_active = 0;
  1295.     break;
  1296.     }
  1297. }
  1298.  
  1299. static UBYTE blit_filltable[256][4][2];
  1300.  
  1301. static void build_filltable(void)
  1302. {
  1303.     unsigned int d, fillmask;
  1304.     int i;
  1305.     for (d = 0; d < 256; d++) {
  1306.     for (i = 0; i < 4; i++) {
  1307.         int fc = i & 1;
  1308.         UBYTE data = d;
  1309.         for (fillmask = 1; fillmask != 0x100; fillmask <<= 1) {
  1310.         UWORD tmp = data;
  1311.         if (fc) {
  1312.             if (i & 2)
  1313.             data |= fillmask;
  1314.             else
  1315.             data ^= fillmask;
  1316.         }
  1317.         if (tmp & fillmask) fc = !fc;
  1318.         }
  1319.         blit_filltable[d][i][0] = data;
  1320.         blit_filltable[d][i][1] = fc;
  1321.     }
  1322.     }
  1323. }
  1324.  
  1325. static __inline__ UWORD *blit_xlateptr(CPTR bltpt, int bytecount)
  1326. {
  1327.     if (!chipmem_bank.check(bltpt,bytecount)) return NULL;
  1328.     return chipmem_bank.xlateaddr(bltpt);
  1329. }
  1330.  
  1331. static __inline__ UWORD *blit_xlateptr_desc(CPTR bltpt, int bytecount)
  1332. {
  1333.     if (!chipmem_bank.check(bltpt-bytecount, bytecount)) return NULL;
  1334.     return chipmem_bank.xlateaddr(bltpt);
  1335. }
  1336.  
  1337. static void blitter_dofast(void) 
  1338. {
  1339.     int i,j;
  1340.     UWORD *bltadatpt = 0, *bltbdatpt = 0, *bltcdatpt = 0, *bltddatpt = 0;
  1341.     UWORD blitahold, blitbhold, bltaold;
  1342.     UBYTE mt = bltcon0 & 0xFF;
  1343.     
  1344.     if (bltcon0 & 0x800) {
  1345.     bltadatpt = blit_xlateptr(bltapt, (blt_info.hblitsize*2+blt_info.bltamod)*blt_info.vblitsize);
  1346.     bltapt += (blt_info.hblitsize*2+blt_info.bltamod)*blt_info.vblitsize;
  1347.     }
  1348.     if (bltcon0 & 0x400) {
  1349.     bltbdatpt = blit_xlateptr(bltbpt, (blt_info.hblitsize*2+blt_info.bltbmod)*blt_info.vblitsize);
  1350.     bltbpt += (blt_info.hblitsize*2+blt_info.bltbmod)*blt_info.vblitsize;
  1351.     }
  1352.     if (bltcon0 & 0x200) {
  1353.     bltcdatpt = blit_xlateptr(bltcpt, (blt_info.hblitsize*2+blt_info.bltcmod)*blt_info.vblitsize);
  1354.     bltcpt += (blt_info.hblitsize*2+blt_info.bltcmod)*blt_info.vblitsize;
  1355.     }
  1356.     if (bltcon0 & 0x100) {
  1357.     bltddatpt = blit_xlateptr(bltdpt, (blt_info.hblitsize*2+blt_info.bltdmod)*blt_info.vblitsize);
  1358.     bltdpt += (blt_info.hblitsize*2+blt_info.bltdmod)*blt_info.vblitsize;
  1359.     }
  1360.     
  1361.     if (blitfunc_dofast[mt] && !blitfill) 
  1362.         (*blitfunc_dofast[mt])(bltadatpt,bltbdatpt,bltcdatpt,bltddatpt,&blt_info);
  1363.     else {
  1364.         WORD bltamodw = blt_info.bltamod/2, bltbmodw = blt_info.bltbmod/2, bltcmodw = blt_info.bltcmod/2, bltdmodw = blt_info.bltdmod/2;
  1365.     /*if (!blitfill) fprintf(stderr, "minterm %x not present\n",mt); */
  1366.         for (j = 0; j < blt_info.vblitsize; j++) {
  1367.         blitfc = !!(bltcon1 & 0x4);
  1368.         for (i = 0; i < blt_info.hblitsize; i++) {
  1369.             if (bltadatpt) blt_info.bltadat = *bltadatpt++;
  1370.             if (bltbdatpt) blt_info.bltbdat = *bltbdatpt++;
  1371.         if (bltcdatpt) blt_info.bltcdat = *bltcdatpt++;
  1372.             bltaold = blt_info.bltadat;
  1373.             if (i == 0) bltaold &= blt_info.bltafwm;
  1374.             if (i== blt_info.hblitsize-1) bltaold &= blt_info.bltalwm;
  1375.             blitahold = (((ULONG)blt_info.blitpreva << 16) | bltaold) >> blt_info.blitashift;
  1376.             blitbhold = (((ULONG)blt_info.blitprevb << 16) | blt_info.bltbdat) >> blt_info.blitbshift;
  1377.             blt_info.bltddat = blit_func(blitahold, blitbhold, blt_info.bltcdat, mt);
  1378.             if (blitfill) {
  1379.             UWORD d = blt_info.bltddat;
  1380.             int ifemode = blitife ? 2 : 0;
  1381.             int fc1 = blit_filltable[d & 255][ifemode + blitfc][1];
  1382.             blt_info.bltddat = (blit_filltable[d & 255][ifemode + blitfc][0] 
  1383.                     + (blit_filltable[d >> 8][ifemode + fc1][0] << 8));
  1384.             blitfc = blit_filltable[d >> 8][ifemode + fc1][1];
  1385.         }
  1386.             blt_info.blitpreva = bltaold; blt_info.blitprevb = blt_info.bltbdat;
  1387.             if (blt_info.bltddat) blt_info.blitzero = 0;
  1388.             if (bltddatpt) *bltddatpt++ = blt_info.bltddat;
  1389.         }
  1390.         if (bltadatpt) bltadatpt += bltamodw;
  1391.         if (bltbdatpt) bltbdatpt += bltbmodw;
  1392.         if (bltcdatpt) bltcdatpt += bltcmodw;
  1393.         if (bltddatpt) bltddatpt += bltdmodw;
  1394.         }
  1395.     }
  1396.     bltstate = BLT_done;
  1397. }
  1398.  
  1399. static void blitter_dofast_desc(void) 
  1400. {
  1401.     int i,j;
  1402.     UWORD *bltadatpt = 0, *bltbdatpt = 0, *bltcdatpt = 0, *bltddatpt = 0;
  1403.     UWORD blitahold, blitbhold, bltaold;
  1404.     WORD bltamodw = blt_info.bltamod/2, bltbmodw = blt_info.bltbmod/2, bltcmodw = blt_info.bltcmod/2, bltdmodw = blt_info.bltdmod/2; 
  1405.     UBYTE mt = bltcon0 & 0xFF;
  1406.     
  1407.     if (bltcon0 & 0x800) {
  1408.     bltadatpt = blit_xlateptr_desc(bltapt, (blt_info.hblitsize*2+blt_info.bltamod)*blt_info.vblitsize);
  1409.     bltapt -= (blt_info.hblitsize*2+blt_info.bltamod)*blt_info.vblitsize;
  1410.     }
  1411.     if (bltcon0 & 0x400) {
  1412.     bltbdatpt = blit_xlateptr_desc(bltbpt, (blt_info.hblitsize*2+blt_info.bltbmod)*blt_info.vblitsize);
  1413.     bltbpt -= (blt_info.hblitsize*2+blt_info.bltbmod)*blt_info.vblitsize;
  1414.     }
  1415.     if (bltcon0 & 0x200) {
  1416.     bltcdatpt = blit_xlateptr_desc(bltcpt, (blt_info.hblitsize*2+blt_info.bltcmod)*blt_info.vblitsize);
  1417.     bltcpt -= (blt_info.hblitsize*2+blt_info.bltcmod)*blt_info.vblitsize;
  1418.     }
  1419.     if (bltcon0 & 0x100) {
  1420.     bltddatpt = blit_xlateptr_desc(bltdpt, (blt_info.hblitsize*2+blt_info.bltdmod)*blt_info.vblitsize);
  1421.     bltdpt -= (blt_info.hblitsize*2+blt_info.bltdmod)*blt_info.vblitsize;
  1422.     }
  1423.     if (blitfunc_dofast_desc[mt] && !blitfill) 
  1424.     (*blitfunc_dofast_desc[mt])(bltadatpt,bltbdatpt,bltcdatpt,bltddatpt,&blt_info);
  1425.     else {
  1426.         WORD bltamodw = blt_info.bltamod/2, bltbmodw = blt_info.bltbmod/2, bltcmodw = blt_info.bltcmod/2, bltdmodw = blt_info.bltdmod/2; 
  1427. /*    if (!blitfill) fprintf(stderr, "minterm %x not present\n",mt);*/
  1428.         for (j = 0; j < blt_info.vblitsize; j++) {
  1429.         blitfc = !!(bltcon1 & 0x4);
  1430.         for (i = 0; i < blt_info.hblitsize; i++) {
  1431.             if (bltadatpt) blt_info.bltadat = *bltadatpt--;
  1432.             if (bltbdatpt) blt_info.bltbdat = *bltbdatpt--;
  1433.             if (bltcdatpt) blt_info.bltcdat = *bltcdatpt--;
  1434.             bltaold = blt_info.bltadat;
  1435.             if (i == 0) bltaold &= blt_info.bltafwm;
  1436.             if (i== blt_info.hblitsize-1) bltaold &= blt_info.bltalwm;
  1437.             blitahold = (((ULONG)bltaold << 16) | blt_info.blitpreva) >> (16-blt_info.blitashift);
  1438.             blitbhold = (((ULONG)blt_info.bltbdat << 16) | blt_info.blitprevb) >> (16-blt_info.blitbshift);
  1439.             blt_info.bltddat = blit_func(blitahold, blitbhold, blt_info.bltcdat, mt);
  1440.             if (blitfill) {
  1441.             UWORD d = blt_info.bltddat;
  1442.             int ifemode = blitife ? 2 : 0;
  1443.             int fc1 = blit_filltable[d & 255][ifemode + blitfc][1];
  1444.             blt_info.bltddat = (blit_filltable[d & 255][ifemode + blitfc][0]
  1445.                     + (blit_filltable[d >> 8][ifemode + fc1][0] << 8));
  1446.             blitfc = blit_filltable[d >> 8][ifemode + fc1][1];
  1447.         }
  1448.             blt_info.blitpreva = bltaold; blt_info.blitprevb = blt_info.bltbdat;
  1449.             if (blt_info.bltddat) blt_info.blitzero = 0;
  1450.             if (bltddatpt) *bltddatpt-- = blt_info.bltddat;
  1451.         }
  1452.         if (bltadatpt) bltadatpt -= bltamodw;
  1453.         if (bltbdatpt) bltbdatpt -= bltbmodw;
  1454.         if (bltcdatpt) bltcdatpt -= bltcmodw;
  1455.         if (bltddatpt) bltddatpt -= bltdmodw;
  1456.         }
  1457.     }
  1458.     bltstate = BLT_done;
  1459. }
  1460.  
  1461. static int blitter_read(void)
  1462. {
  1463.     if (bltcon0 & 0xe00){
  1464.     if (!dmaen(DMA_BLITTER)) return 1; /* blitter stopped */
  1465.     if (!blitline){
  1466.         if (bltcon0 & 0x800) blt_info.bltadat = chipmem_bank.wget(bltapt);
  1467.         if (bltcon0 & 0x400) blt_info.bltbdat = chipmem_bank.wget(bltbpt);
  1468.     }
  1469.     if (bltcon0 & 0x200) blt_info.bltcdat = chipmem_bank.wget(bltcpt);
  1470.     }
  1471.     bltstate = BLT_work;
  1472.     return (bltcon0 & 0xE00) != 0;
  1473. }
  1474.  
  1475. static int blitter_write(void)
  1476. {
  1477.     if (blt_info.bltddat) blt_info.blitzero = 0;
  1478.     if ((bltcon0 & 0x100) || blitline){
  1479.     if (!dmaen(DMA_BLITTER)) return 1;
  1480.     chipmem_bank.wput(bltdpt, blt_info.bltddat);
  1481.     }
  1482.     bltstate = BLT_next;
  1483.     return (bltcon0 & 0x100) != 0;
  1484. }
  1485.  
  1486. static void blitter_blit(void)
  1487. {
  1488.     UWORD blitahold,blitbhold,blitchold;
  1489.     UWORD bltaold;
  1490.     
  1491.     if (blitdesc) {
  1492.     UWORD bltamask = 0xffff;
  1493.     
  1494.     if (!blitlpos) { bltamask &= blt_info.bltafwm; }
  1495.     if (blitlpos == (blt_info.hblitsize - 1)) { bltamask &= blt_info.bltalwm; }
  1496.     bltaold = blt_info.bltadat & bltamask;
  1497.  
  1498.     blitahold = (((ULONG)bltaold << 16) | blt_info.blitpreva) >> (16-blt_info.blitashift);
  1499.     blitbhold = (((ULONG)blt_info.bltbdat << 16) | blt_info.blitprevb) >> (16-blt_info.blitbshift);
  1500.     blitchold = blt_info.bltcdat;
  1501.     } else {
  1502.     UWORD bltamask = 0xffff;
  1503.     
  1504.     if (!blitlpos) { bltamask &= blt_info.bltafwm; }
  1505.     if (blitlpos == (blt_info.hblitsize - 1)) { bltamask &= blt_info.bltalwm; }
  1506.     bltaold = blt_info.bltadat & bltamask;
  1507.  
  1508.     blitahold = (((ULONG)blt_info.blitpreva << 16) | bltaold) >> blt_info.blitashift;
  1509.     blitbhold = (((ULONG)blt_info.blitprevb << 16) | blt_info.bltbdat) >> blt_info.blitbshift;
  1510.     blitchold = blt_info.bltcdat;
  1511.     }
  1512.     blt_info.bltddat = 0;
  1513.     blt_info.bltddat = blit_func(blitahold, blitbhold, blitchold, bltcon0 & 0xFF);
  1514.     if (blitfill){
  1515.     UWORD fillmask;
  1516.     for (fillmask = 1; fillmask; fillmask <<= 1){
  1517.         UWORD tmp = blt_info.bltddat;
  1518.         if (blitfc) {
  1519.         if (blitife)
  1520.             blt_info.bltddat |= fillmask;
  1521.         else
  1522.             blt_info.bltddat ^= fillmask;
  1523.         }
  1524.         if (tmp & fillmask) blitfc = !blitfc;
  1525.     }
  1526.     }
  1527.     bltstate = BLT_write;
  1528.     blt_info.blitpreva = bltaold; blt_info.blitprevb = blt_info.bltbdat;
  1529. }
  1530.  
  1531. static void blitter_nxblit(void)
  1532. {
  1533.     bltstate = BLT_read;
  1534.     if (blitdesc){
  1535.     if (++blitlpos == blt_info.hblitsize) {
  1536.         if (--blt_info.vblitsize == 0) {
  1537.         bltstate = BLT_done;
  1538. #if FAST_BLITTER == 0
  1539.         custom_bank.wput(0xDFF09C,0x8040);
  1540. #endif
  1541.         }
  1542.         blitfc = bltcon1 & 0x4;
  1543.  
  1544.         blitlpos = 0;
  1545.         if (bltcon0 & 0x800) bltapt -= 2+blt_info.bltamod; 
  1546.         if (bltcon0 & 0x400) bltbpt -= 2+blt_info.bltbmod; 
  1547.         if (bltcon0 & 0x200) bltcpt -= 2+blt_info.bltcmod; 
  1548.         if (bltcon0 & 0x100) bltdpt -= 2+blt_info.bltdmod;
  1549.     } else {
  1550.         if (bltcon0 & 0x800) bltapt -= 2; 
  1551.         if (bltcon0 & 0x400) bltbpt -= 2; 
  1552.         if (bltcon0 & 0x200) bltcpt -= 2; 
  1553.         if (bltcon0 & 0x100) bltdpt -= 2;        
  1554.     }
  1555.     } else {
  1556.     if (++blitlpos == blt_info.hblitsize) {
  1557.         if (--blt_info.vblitsize == 0) { 
  1558.         bltstate = BLT_done;
  1559. #if FAST_BLITTER == 0
  1560.         custom_bank.wput(0xDFF09C,0x8040);
  1561. #endif
  1562.         }
  1563.         blitlpos = 0;
  1564.         if (bltcon0 & 0x800) bltapt += 2+blt_info.bltamod; 
  1565.         if (bltcon0 & 0x400) bltbpt += 2+blt_info.bltbmod; 
  1566.         if (bltcon0 & 0x200) bltcpt += 2+blt_info.bltcmod; 
  1567.         if (bltcon0 & 0x100) bltdpt += 2+blt_info.bltdmod;
  1568.     } else {
  1569.         if (bltcon0 & 0x800) bltapt += 2; 
  1570.         if (bltcon0 & 0x400) bltbpt += 2; 
  1571.         if (bltcon0 & 0x200) bltcpt += 2; 
  1572.         if (bltcon0 & 0x100) bltdpt += 2;
  1573.     }
  1574.     }
  1575. }
  1576.  
  1577. static __inline__ void blitter_line_incx(void)
  1578. {
  1579.     blinea >>= 1;
  1580.     if (!blinea) {
  1581.     blinea = 0x8000;
  1582.     bltcnxlpt += 2;
  1583.     bltdnxlpt += 2;
  1584.     }
  1585. }
  1586.  
  1587. static __inline__ void blitter_line_decx(void)
  1588. {
  1589.     blinea <<= 1;
  1590.     if (!blinea) {
  1591.     blinea = 1;
  1592.     bltcnxlpt -= 2;
  1593.     bltdnxlpt -= 2;
  1594.     }
  1595. }
  1596.  
  1597. static __inline__ void blitter_line_decy(void)
  1598. {
  1599.     bltcnxlpt -= blt_info.bltcmod;
  1600.     bltdnxlpt -= blt_info.bltcmod; /* ??? am I wrong or doesn't KS1.3 set bltdmod? */
  1601.     blitonedot = 0;
  1602. }
  1603.  
  1604. static __inline__ void blitter_line_incy(void)
  1605. {
  1606.     bltcnxlpt += blt_info.bltcmod;
  1607.     bltdnxlpt += blt_info.bltcmod; /* ??? */
  1608.     blitonedot = 0;
  1609. }
  1610.  
  1611. static void blitter_line(void)
  1612. {
  1613.     UWORD blitahold = blinea, blitbhold = blineb & 1 ? 0xFFFF : 0, blitchold = blt_info.bltcdat;
  1614.     blt_info.bltddat = 0;
  1615.     
  1616.     if (blitsing && blitonedot) blitahold = 0;
  1617.     blitonedot = 1;
  1618.     blt_info.bltddat = blit_func(blitahold, blitbhold, blitchold, bltcon0 & 0xFF);
  1619.     if (!blitsign){
  1620.     bltapt += (WORD)blt_info.bltamod;
  1621.     if (bltcon1 & 0x10){
  1622.         if (bltcon1 & 0x8)
  1623.             blitter_line_decy();
  1624.         else
  1625.             blitter_line_incy();
  1626.     } else {
  1627.         if (bltcon1 & 0x8)
  1628.             blitter_line_decx();
  1629.         else 
  1630.             blitter_line_incx();
  1631.     }
  1632.     } else {
  1633.     bltapt += (WORD)blt_info.bltbmod;
  1634.     }
  1635.     if (bltcon1 & 0x10){
  1636.     if (bltcon1 & 0x4)
  1637.         blitter_line_decx();
  1638.     else
  1639.         blitter_line_incx();
  1640.     } else {
  1641.     if (bltcon1 & 0x4)
  1642.         blitter_line_decy();
  1643.     else
  1644.         blitter_line_incy();
  1645.     }
  1646.     blitsign = 0 > (WORD)bltapt;
  1647.     bltstate = BLT_write;
  1648. }
  1649.  
  1650. static __inline__ void blitter_nxline(void)
  1651. {
  1652.     bltcpt = bltcnxlpt;
  1653.     bltdpt = bltdnxlpt;
  1654.     blineb = (blineb << 1) | (blineb >> 15);
  1655.     if (--blt_info.vblitsize == 0) {
  1656.     bltstate = BLT_done;
  1657. #if FAST_BLITTER == 0
  1658.     custom_bank.wput(0xDFF09C,0x8040);
  1659. #endif
  1660.     } else {
  1661.     bltstate = BLT_read;
  1662.     }
  1663. }
  1664.  
  1665. static void blit_init(void)
  1666. {
  1667.     blitlpos = 0;
  1668.     blt_info.blitzero = 1; blt_info.blitpreva = blt_info.blitprevb = 0;
  1669.     blitline = bltcon1 & 1;
  1670.     blt_info.blitashift = bltcon0 >> 12; blt_info.blitbshift = bltcon1 >> 12;
  1671.     
  1672.     if (blitline) {
  1673.     if (blt_info.hblitsize != 2)
  1674.         fprintf(stderr, "weird hblitsize in linemode: %d\n", blt_info.hblitsize);
  1675.     bltcnxlpt = bltcpt;
  1676.     bltdnxlpt = bltdpt;
  1677.     blitsing = bltcon1 & 0x2;
  1678.     blinea = blt_info.bltadat >> blt_info.blitashift;
  1679.     blineb = (blt_info.bltbdat >> blt_info.blitbshift) | (blt_info.bltbdat << (16-blt_info.blitbshift));
  1680. #if 0
  1681.     if (blineb != 0xFFFF && blineb != 0)
  1682.         fprintf(stderr, "%x %x %d %x\n", blineb, blt_info.bltbdat, blt_info.blitbshift, bltcon1);
  1683. #endif
  1684.     blitsign = bltcon1 & 0x40; 
  1685.     blitonedot = 0;
  1686.     } else {
  1687.     blitfc = !!(bltcon1 & 0x4);
  1688.     blitife = bltcon1 & 0x8;
  1689.     blitfill = bltcon1 & 0x18;
  1690.     if ((bltcon1 & 0x18) == 0x18) {
  1691.         /* Digital "Trash" demo does this; others too. Apparently, no
  1692.          * negative effects. */
  1693.         static int warn = 1;
  1694.         if (warn)
  1695.             fprintf(stderr, "warning: weird fill mode (further messages suppressed)\n");
  1696.         warn = 0;
  1697.     }
  1698.     blitdesc = bltcon1 & 0x2;
  1699.     if (blitfill && !blitdesc)
  1700.         fprintf(stderr, "warning: blitter fill without desc\n");
  1701.     }
  1702. }
  1703.  
  1704. static void actually_do_blit(void)
  1705. {
  1706.     if (blitline) {
  1707.     do {
  1708.         blitter_read();
  1709.         blitter_line();
  1710.         blitter_write();
  1711.         blitter_nxline();
  1712.     } while (bltstate != BLT_done);
  1713.     } else {
  1714.     /*blitcount[bltcon0 & 0xff]++;  blitter debug */
  1715.     if (blitdesc) blitter_dofast_desc();
  1716.     else blitter_dofast();
  1717.     }
  1718. }
  1719.  
  1720. #ifdef DEFERRED_INT
  1721. static void defer_int_handler(void)
  1722. {
  1723.     if (!dmaen(DMA_BLITTER)) {
  1724.     eventtab[ev_deferint].active = 1;
  1725.     eventtab[ev_deferint].oldcycles = cycles;
  1726.     eventtab[ev_deferint].evtime = 10; /* wait a little */
  1727.     return; /* gotta come back later. */
  1728.     }
  1729.     actually_do_blit();
  1730.     
  1731.     INTREQ(0x8040);
  1732.     eventtab[ev_deferint].active = 0;
  1733.     specialflags &= ~SPCFLAG_BLTNASTY;
  1734. }
  1735. #endif
  1736.  
  1737. void do_blitter(void)
  1738. {
  1739. #if FAST_BLITTER == 0
  1740.     /* I'm not sure all this bltstate stuff is really necessary.
  1741.      * Most programs should be OK if the blit is done as soon as BLTSIZE is
  1742.      * written to, and the BLTFINISH bit is set some time after that.
  1743.      * This code here is nowhere near exact.
  1744.      */
  1745.     do {    
  1746.     switch(bltstate) {
  1747.      case BLT_init:
  1748.         blit_init();
  1749.         bltstate = BLT_read;
  1750.         /* fall through */
  1751.      case BLT_read:
  1752.         if (blitter_read())
  1753.             break;
  1754.         /* fall through */
  1755.      case BLT_work:
  1756.         if (blitline)
  1757.             blitter_line(); 
  1758.         else 
  1759.             blitter_blit();
  1760.         /* fall through */
  1761.      case BLT_write:
  1762.         if (blitter_write())
  1763.             break;
  1764.         /* fall through */
  1765.      case BLT_next:
  1766.         if (blitline)
  1767.             blitter_nxline();
  1768.         else 
  1769.             blitter_nxblit();
  1770.         break;
  1771.      case BLT_done:
  1772.         specialflags &= ~SPCFLAG_BLIT;
  1773.         break;
  1774.     }
  1775.     } while(bltstate != BLT_done && dmaen(DMA_BLITTER)
  1776.         && dmaen(DMA_BLITPRI));  /* blitter nasty -> no time for CPU */
  1777. #else
  1778.     {
  1779.     long int blit_cycles = 2;
  1780.  
  1781.     if (!blitline) {
  1782.         if (bltcon0 & 0x400)
  1783.         blit_cycles++;
  1784.         if ((bltcon0 & 0x300) == 0x300)
  1785.         blit_cycles++;
  1786.         blit_cycles *= blt_info.vblitsize * blt_info.hblitsize;
  1787.     }
  1788.     blit_init();
  1789.     
  1790.     eventtab[ev_deferint].active = 1;
  1791.     eventtab[ev_deferint].oldcycles = cycles;
  1792.     eventtab[ev_deferint].evtime = blit_cycles;
  1793.     events_schedule();
  1794.  
  1795.     specialflags &= ~SPCFLAG_BLIT;
  1796.     if (dmaen(DMA_BLITPRI))
  1797.         specialflags |= SPCFLAG_BLTNASTY;
  1798.     }
  1799. #endif
  1800. }
  1801.  
  1802. static void maybe_blit(void)
  1803. {
  1804.     static int warned = 0;
  1805.     if (bltstate == BLT_done)
  1806.     return;
  1807.     
  1808.     if (!warned) {
  1809.     warned = 1;
  1810.     fprintf(stderr, "warning: Program does not wait for blitter (no further messages)\n");
  1811.     }
  1812.     if (!eventtab[ev_deferint].active)
  1813.     printf("FOO!!?\n");
  1814.     actually_do_blit();
  1815.     eventtab[ev_deferint].active = 0;
  1816.     specialflags &= ~SPCFLAG_BLTNASTY;
  1817. }
  1818.  
  1819. static int disk_int_defer = 0;
  1820.  
  1821. void do_disk(void)
  1822. {
  1823.     if (dskdmaen > 1 && dmaen(0x10)){
  1824.     if (--dsktime == 0) {
  1825.         dsktime = dskdelay;
  1826.         if (dsklen & 0x4000){
  1827.         UWORD dsksync_check;
  1828.         DISK_GetData(&dsksync_check, &dskbyte);
  1829.         dskbyte |= 0x8000;
  1830.         if (dsksynced || !(adkcon & 0x400)) {
  1831.             *mfmwrite++ = chipmem_bank.wget(dskpt); dskpt += 2;
  1832.             if (--dsklength == 0) {
  1833.             DISK_WriteData();
  1834.             custom_bank.wput(0xDFF09C, 0x8002); /*INTREQ->DSKBLK */
  1835.             dskdmaen = 0;
  1836.             specialflags &= ~SPCFLAG_DISK;
  1837.             }
  1838.         }
  1839.         if (dsksync_check == dsksync) {
  1840.             custom_bank.wput(0xDFF09C, 0x9000);
  1841.             dsksynced = 1;
  1842.         }
  1843.         } else {
  1844. #if defined(NO_FAST_DISK)
  1845.         DISK_GetData(&dskmfm, &dskbyte);
  1846.         dskbyte |= 0x8000;
  1847.         if (dsksynced || !(adkcon & 0x400)){
  1848.             chipmem_bank.wput(dskpt, dskmfm); dskpt += 2;
  1849.             if (--dsklength == 0) {
  1850.             custom_bank.wput(0xDFF09C, 0x8002);
  1851.             dskdmaen = 0;
  1852.             specialflags &= ~SPCFLAG_DISK;
  1853.             }
  1854.         }
  1855.         if (dskmfm == dsksync) {
  1856.             custom_bank.wput(0xDFF09C,0x9000);
  1857.             dsksynced = 1;
  1858.         }
  1859. #else
  1860.         int ntries = 100000;
  1861.         do {
  1862.             DISK_GetData(&dskmfm, &dskbyte);
  1863.             dskbyte |= 0x8000;
  1864.             if (dsksynced || !(adkcon & 0x400)){
  1865.             chipmem_bank.wput(dskpt, dskmfm); dskpt += 2;
  1866.             if (--dsklength == 0) {
  1867.                 disk_int_defer = 5;
  1868.                 dskdmaen = 0;
  1869.                 specialflags &= ~SPCFLAG_DISK;
  1870.             }
  1871.             }
  1872.             if (dskmfm == dsksync) {
  1873.             custom_bank.wput(0xDFF09C,0x9000);
  1874.             dsksynced = 1;
  1875.             }
  1876.         } while ((specialflags & SPCFLAG_DISK) && --ntries);
  1877. #endif
  1878.         }
  1879.     }
  1880.     }
  1881. }
  1882.  
  1883. static __inline__ void pfield_fetchdata(void)
  1884. {
  1885.     if (dmaen(0x100) && pfield_linedmaon) {
  1886.     switch(bplplanecnt){
  1887.      case 8:
  1888.         bpl8dat = chipmem_bank.wget(bplpt[7]); bplpt[7] += 2; bpl8dat <<= 7;
  1889.      case 7:
  1890.         bpl7dat = chipmem_bank.wget(bplpt[6]); bplpt[6] += 2; bpl7dat <<= 6;
  1891.      case 6:
  1892.         bpl6dat = chipmem_bank.wget(bplpt[5]); bplpt[5] += 2; bpl6dat <<= 5;
  1893.      case 5:
  1894.         bpl5dat = chipmem_bank.wget(bplpt[4]); bplpt[4] += 2; bpl5dat <<= 4;
  1895.      case 4:
  1896.         bpl4dat = chipmem_bank.wget(bplpt[3]); bplpt[3] += 2; bpl4dat <<= 3;
  1897.      case 3:
  1898.         bpl3dat = chipmem_bank.wget(bplpt[2]); bplpt[2] += 2; bpl3dat <<= 2;
  1899.      case 2:
  1900.         bpl2dat = chipmem_bank.wget(bplpt[1]); bplpt[1] += 2; bpl2dat <<= 1;
  1901.      case 1:
  1902.         bpl1dat = chipmem_bank.wget(bplpt[0]); bplpt[0] += 2;
  1903.     }
  1904.     }
  1905. }
  1906.  
  1907. static void do_sprites(int currvp, int currhp)
  1908. {   
  1909.     int i;
  1910.     int maxspr = currhp/4 -0x18/ 4;
  1911.     
  1912.     if (currvp == 0)
  1913.     return;
  1914.     if (maxspr < 0)
  1915.     return;
  1916.     if (maxspr > 7)
  1917.     maxspr = 7;
  1918.     
  1919.     for(i = last_sprite; i <= maxspr; i++) {
  1920.     int vstart = (bpl_info.sprpos[i] >> 8) | ((bpl_info.sprctl[i] << 6) & 0x100);
  1921.     int vstop = (bpl_info.sprctl[i] >> 8) | ((bpl_info.sprctl[i] << 7) & 0x100);
  1922.     if ((vstart <= currvp && vstop >= currvp) || spron[i] == 1) {
  1923.         if (dmaen(0x20)) {
  1924.         UWORD data1 = chipmem_bank.wget(sprpt[i]);
  1925.         UWORD data2 = chipmem_bank.wget(sprpt[i]+2);
  1926.         sprpt[i] += 4;
  1927.         
  1928.         if (vstop != currvp && spron[i] != 1) {
  1929.             /* Hack for X mouse auto-calibration */
  1930.             if (i == 0 && !sprvbfl && ((bpl_info.sprpos[0]&0xff)<<2)>0x60) {
  1931.             int old0ctl = spr0ctl, old0pos = spr0pos;
  1932.             spr0ctl=bpl_info.sprctl[0];
  1933.             spr0pos=bpl_info.sprpos[0];
  1934.             sprvbfl=2;
  1935.             }
  1936.             SPRxDATB_1(data2, i);
  1937.             SPRxDATA_1(data1, i);
  1938.         } else {
  1939.             SPRxPOS_1(data1, i);
  1940.             SPRxCTL_1(data2, i);
  1941.         }
  1942.         }
  1943.     }
  1944.     }
  1945.     last_sprite = maxspr + 1;
  1946. }
  1947.  
  1948. static __inline__ void pfield_modulos(int add)
  1949. {
  1950.     switch(bplplanecnt){
  1951.      case 8:
  1952.     bplpt[7] += add + bpl2mod;
  1953.      case 7:
  1954.     bplpt[6] += add + bpl1mod;
  1955.      case 6:
  1956.     bplpt[5] += add + bpl2mod;
  1957.      case 5:
  1958.     bplpt[4] += add + bpl1mod;
  1959.      case 4:
  1960.     bplpt[3] += add + bpl2mod;
  1961.      case 3:
  1962.     bplpt[2] += add + bpl1mod;
  1963.      case 2:
  1964.     bplpt[1] += add + bpl2mod;
  1965.      case 1:
  1966.     bplpt[0] += add + bpl1mod;
  1967.     }
  1968. }
  1969.  
  1970. void pfield_sprite_l (int num, int sprxp, UWORD data, UWORD datb)
  1971. {
  1972.     int i;
  1973.     for(i = 15; i >= 0; i--) {
  1974.     int sprxpos = sprxp + i;
  1975.     if (spixstate[sprxpos] & ((1 << num)-1))
  1976.         continue;
  1977.  
  1978.     if ((bpl_info.sprctl[num] & 0x80) && (num & 1)) {
  1979.         /* Attached sprite */
  1980.         int col = ((data << 2) & 4) + ((datb << 3) & 8);
  1981.         if (col) {
  1982.         spixels[sprxpos] = col;
  1983.         spixstate[sprxpos] = 1 << num;
  1984.         }
  1985.         spixstate[sprxpos] |= 1 << (num-1);
  1986.     } else {            
  1987.         int col = (data & 1) | ((datb << 1) & 2);
  1988.         if (spixstate[sprxpos] & (1 << num)) {
  1989.         /* finish attached sprite */
  1990.         /* Did the upper half of the sprite have any bits set? */
  1991.         if (spixstate[sprxpos] & (1 << (num+1)))
  1992.             col += spixels[sprxpos];
  1993.         if (!col) {
  1994.             spixstate[sprxpos] &= ~(3 << num);
  1995.         }
  1996.         } else {
  1997.         if (col) {
  1998.             col |= (num & 6) << 1;
  1999.         }
  2000.         }
  2001.         if (col) {
  2002.         spixels[sprxpos] = col;
  2003.         spixstate[sprxpos] = 1<<num;
  2004.         }
  2005.     }
  2006.     data >>= 1;
  2007.     datb >>= 1;
  2008.     }
  2009. }
  2010.  
  2011. void pfield_sprite_h (int num, int sprxp, UWORD data, UWORD datb)
  2012. {
  2013.     int i;
  2014.     for(i = 15; i >= 0; i--) {
  2015.     int sprxpos = sprxp + i*2;
  2016.     if (spixstate[sprxpos] & ((1 << num)-1))
  2017.         continue;
  2018.  
  2019.     if ((bpl_info.sprctl[num] & 0x80) && (num & 1)) {
  2020.         /* Attached sprite */
  2021.         int col = ((data << 2) & 4) + ((datb << 3) & 8);
  2022.         if (col) {
  2023.         spixels[sprxpos] = col;
  2024.         spixels[sprxpos+1] = col;
  2025.         spixstate[sprxpos] = 1 << num;
  2026.         spixstate[sprxpos+1] = 1 << num;
  2027.         }
  2028.         spixstate[sprxpos] |= 1 << (num-1);
  2029.         spixstate[sprxpos+1] |= 1 << (num-1);
  2030.     } else {            
  2031.         int col = (data & 1) | ((datb << 1) & 2);
  2032.         if (spixstate[sprxpos] & (1 << num)) {
  2033.         /* finish attached sprite */
  2034.         /* Did the upper half of the sprite have any bits set? */
  2035.         if (spixstate[sprxpos] & (1 << (num+1)))
  2036.             col += spixels[sprxpos];
  2037.         if (!col) {
  2038.             spixstate[sprxpos] = spixstate[sprxpos+1] &= ~(3 << num);
  2039.         }
  2040.         } else {
  2041.         if (col) {
  2042.             col |= (num & 6) << 1;
  2043.         }
  2044.         }
  2045.         if (col) {
  2046.         spixels[sprxpos] = col;
  2047.         spixels[sprxpos+1] = col;
  2048.         spixstate[sprxpos] = 1<<num;
  2049.         spixstate[sprxpos+1] = 1<<num;
  2050.         }
  2051.     }
  2052.     data >>= 1;
  2053.     datb >>= 1;
  2054.     }
  2055. }
  2056.  
  2057. static __inline__ UWORD *pfield_xlateptr(CPTR plpt, int bytecount)
  2058. {
  2059.     if (!chipmem_bank.check(plpt,bytecount)) {
  2060.     static int count = 0;
  2061.     if (count < 5) {
  2062.         count++;
  2063.         fprintf(stderr, "Warning: Bad playfield pointer");
  2064.         if (count == 5) fprintf(stderr, " (no further warnings)");
  2065.         fprintf(stderr, "\n");
  2066.     }
  2067.     return NULL;
  2068.     }
  2069.     return chipmem_bank.xlateaddr(plpt);
  2070. }
  2071.  
  2072. static void pfield_doline_slow_h(int currhpos)
  2073. {
  2074.     int xpos = currhpos * 4 - 0x60;
  2075.         
  2076.     if (bplhires) {
  2077.     int offs1 = xpos + 16 + bpldelay1*2;
  2078.     int offs2 = xpos + 16 + bpldelay2*2;
  2079.     
  2080.     int pix;
  2081.     for(pix = 15; pix >= 0; pix--) {
  2082.         switch(bplplanecnt) {
  2083.          case 8:
  2084.         pixdata.apixels[pix + offs2] |= bpl8dat & 0x80; bpl8dat >>= 1;
  2085.          case 7:
  2086.         pixdata.apixels[pix + offs1] |= bpl7dat & 0x40; bpl7dat >>= 1;
  2087.          case 6:
  2088.         pixdata.apixels[pix + offs2] |= bpl6dat & 0x20; bpl6dat >>= 1;
  2089.          case 5:
  2090.         pixdata.apixels[pix + offs1] |= bpl5dat & 0x10; bpl5dat >>= 1;
  2091.          case 4:
  2092.         pixdata.apixels[pix + offs2] |= bpl4dat & 0x8; bpl4dat >>= 1;
  2093.          case 3:
  2094.         pixdata.apixels[pix + offs1] |= bpl3dat & 0x4; bpl3dat >>= 1;
  2095.          case 2:
  2096.         pixdata.apixels[pix + offs2] |= bpl2dat & 0x2; bpl2dat >>= 1;
  2097.          case 1:
  2098.         pixdata.apixels[pix + offs1] |= bpl1dat & 0x1; bpl1dat >>= 1;
  2099.         }
  2100.     }
  2101.     } else {
  2102.     int offs1 = xpos + 32 + bpldelay1*2;
  2103.     int offs2 = xpos + 32 + bpldelay2*2;
  2104.     
  2105.     int pix;
  2106.     for(pix = 30; pix >= 0; pix -= 2) {
  2107.         switch(bplplanecnt) {
  2108.          case 8:
  2109.         pixdata.apixels[pix + offs2] |= bpl8dat & 0x80;
  2110.         pixdata.apixels[pix + offs2 + 1] |= bpl8dat & 0x80; bpl8dat >>= 1;
  2111.          case 7:
  2112.         pixdata.apixels[pix + offs1] |= bpl7dat & 0x40; 
  2113.         pixdata.apixels[pix + offs1 + 1] |= bpl7dat & 0x40; bpl7dat >>= 1;
  2114.          case 6:
  2115.         pixdata.apixels[pix + offs2] |= bpl6dat & 0x20;
  2116.         pixdata.apixels[pix + offs2 + 1] |= bpl6dat & 0x20; bpl6dat >>= 1;
  2117.          case 5:
  2118.         pixdata.apixels[pix + offs1] |= bpl5dat & 0x10;
  2119.         pixdata.apixels[pix + offs1 + 1] |= bpl5dat & 0x10; bpl5dat >>= 1;
  2120.          case 4:
  2121.         pixdata.apixels[pix + offs2] |= bpl4dat & 0x8;
  2122.         pixdata.apixels[pix + offs2 + 1] |= bpl4dat & 0x8; bpl4dat >>= 1;
  2123.          case 3:
  2124.         pixdata.apixels[pix + offs1] |= bpl3dat & 0x4; 
  2125.         pixdata.apixels[pix + offs1 + 1] |= bpl3dat & 0x4; bpl3dat >>= 1;
  2126.          case 2:
  2127.         pixdata.apixels[pix + offs2] |= bpl2dat & 0x2; 
  2128.         pixdata.apixels[pix + offs2 + 1] |= bpl2dat & 0x2; bpl2dat >>= 1;
  2129.          case 1:
  2130.         pixdata.apixels[pix + offs1] |= bpl1dat & 0x1; 
  2131.         pixdata.apixels[pix + offs1 + 1] |= bpl1dat & 0x1; bpl1dat >>= 1;
  2132.         }
  2133.     }
  2134.     }    
  2135. }
  2136.  
  2137. static void pfield_doline_slow_l(int currhpos)
  2138. {
  2139.     int xpos = currhpos * 2 - 0x30;
  2140.     
  2141.     if (bplhires) {
  2142.     int offs1 = xpos + 8 + bpldelay1;
  2143.     int offs2 = xpos + 8 + bpldelay2;
  2144.     
  2145.     int pix;
  2146.     for(pix = 7; pix >= 0; pix--) {
  2147.         switch(bplplanecnt) {
  2148.          case 8:
  2149.         pixdata.apixels[pix + offs2] |= bpl8dat & 0x80; bpl8dat >>= 2;
  2150.          case 7:
  2151.         pixdata.apixels[pix + offs1] |= bpl7dat & 0x40; bpl7dat >>= 2;
  2152.          case 6:
  2153.         pixdata.apixels[pix + offs2] |= bpl6dat & 0x20; bpl6dat >>= 2;
  2154.          case 5:
  2155.         pixdata.apixels[pix + offs1] |= bpl5dat & 0x10; bpl5dat >>= 2;
  2156.          case 4:
  2157.         pixdata.apixels[pix + offs2] |= bpl4dat & 0x8; bpl4dat >>= 2;
  2158.          case 3:
  2159.         pixdata.apixels[pix + offs1] |= bpl3dat & 0x4; bpl3dat >>= 2;
  2160.          case 2:
  2161.         pixdata.apixels[pix + offs2] |= bpl2dat & 0x2; bpl2dat >>= 2;
  2162.          case 1:
  2163.         pixdata.apixels[pix + offs1] |= bpl1dat & 0x1; bpl1dat >>= 2;
  2164.         }
  2165.     }
  2166.     } else {
  2167.     int offs1 = xpos + 16 + bpldelay1;
  2168.     int offs2 = xpos + 16 + bpldelay2;
  2169.     
  2170.     int pix;
  2171.     for(pix = 15; pix >= 0; pix --) {
  2172.         switch(bplplanecnt) {
  2173.          case 8:
  2174.         pixdata.apixels[pix + offs2] |= bpl8dat & 0x80; bpl8dat >>= 1;
  2175.          case 7:
  2176.         pixdata.apixels[pix + offs1] |= bpl7dat & 0x40; bpl7dat >>= 1;
  2177.          case 6:
  2178.         pixdata.apixels[pix + offs2] |= bpl6dat & 0x20; bpl6dat >>= 1;
  2179.          case 5:
  2180.         pixdata.apixels[pix + offs1] |= bpl5dat & 0x10; bpl5dat >>= 1;
  2181.          case 4:
  2182.         pixdata.apixels[pix + offs2] |= bpl4dat & 0x8; bpl4dat >>= 1;
  2183.          case 3:
  2184.         pixdata.apixels[pix + offs1] |= bpl3dat & 0x4; bpl3dat >>= 1;
  2185.          case 2:
  2186.         pixdata.apixels[pix + offs2] |= bpl2dat & 0x2; bpl2dat >>= 1;
  2187.          case 1:
  2188.         pixdata.apixels[pix + offs1] |= bpl1dat & 0x1; bpl1dat >>= 1;
  2189.         }
  2190.     }
  2191.     }    
  2192. }
  2193.  
  2194. ULONG hirestab_h[256][2];
  2195. ULONG lorestab_h[256][4];
  2196.  
  2197. ULONG hirestab_l[256][1];
  2198. ULONG lorestab_l[256][2];
  2199.  
  2200. static void gen_pfield_tables(void)
  2201. {
  2202.     int i;
  2203.     union {
  2204.     struct {
  2205.         UBYTE a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p;
  2206.     } foo;
  2207.     struct {
  2208.         ULONG a, b, c, d;
  2209.     } bar;
  2210.     } baz;
  2211.     
  2212.     for (i = 0; i < 256; i++) {
  2213.     /* We lose every second pixel in HiRes if UAE runs in a 320x200 screen. */
  2214.     baz.foo.a = i & 64 ? 1 : 0;
  2215.     baz.foo.b = i & 16 ? 1 : 0;
  2216.     baz.foo.c = i & 4 ? 1 : 0;
  2217.     baz.foo.d = i & 1 ? 1 : 0;
  2218.     hirestab_l[i][0] = baz.bar.a;
  2219.     
  2220.     baz.foo.a = i & 128 ? 1 : 0;
  2221.     baz.foo.b = i & 64 ? 1 : 0;
  2222.     baz.foo.c = i & 32 ? 1 : 0;
  2223.     baz.foo.d = i & 16 ? 1 : 0;
  2224.     baz.foo.e = i & 8 ? 1 : 0;
  2225.     baz.foo.f = i & 4 ? 1 : 0;
  2226.     baz.foo.g = i & 2 ? 1 : 0;
  2227.     baz.foo.h = i & 1 ? 1 : 0;
  2228.     lorestab_l[i][0] = baz.bar.a;
  2229.     lorestab_l[i][1] = baz.bar.b;
  2230.     }
  2231.     
  2232.     for (i = 0; i < 256; i++) {
  2233.     baz.foo.a = i & 128 ? 1 : 0;
  2234.     baz.foo.b = i & 64 ? 1 : 0;
  2235.     baz.foo.c = i & 32 ? 1 : 0;
  2236.     baz.foo.d = i & 16 ? 1 : 0;
  2237.     baz.foo.e = i & 8 ? 1 : 0;
  2238.     baz.foo.f = i & 4 ? 1 : 0;
  2239.     baz.foo.g = i & 2 ? 1 : 0;
  2240.     baz.foo.h = i & 1 ? 1 : 0;
  2241.     hirestab_h[i][0] = baz.bar.a;
  2242.     hirestab_h[i][1] = baz.bar.b;
  2243.     
  2244.     baz.foo.a = i & 128 ? 1 : 0;
  2245.     baz.foo.b = i & 128 ? 1 : 0;
  2246.     baz.foo.c = i & 64 ? 1 : 0;
  2247.     baz.foo.d = i & 64 ? 1 : 0;
  2248.     baz.foo.e = i & 32 ? 1 : 0;
  2249.     baz.foo.f = i & 32 ? 1 : 0;
  2250.     baz.foo.g = i & 16 ? 1 : 0;
  2251.     baz.foo.h = i & 16 ? 1 : 0;
  2252.     baz.foo.i = i & 8 ? 1 : 0;
  2253.     baz.foo.j = i & 8 ? 1 : 0;
  2254.     baz.foo.k = i & 4 ? 1 : 0;
  2255.     baz.foo.l = i & 4 ? 1 : 0;
  2256.     baz.foo.m = i & 2 ? 1 : 0;
  2257.     baz.foo.n = i & 2 ? 1 : 0;
  2258.     baz.foo.o = i & 1 ? 1 : 0;
  2259.     baz.foo.p = i & 1 ? 1 : 0;
  2260.     lorestab_h[i][0] = baz.bar.a;
  2261.     lorestab_h[i][1] = baz.bar.b;
  2262.     lorestab_h[i][2] = baz.bar.c;
  2263.     lorestab_h[i][3] = baz.bar.d;
  2264.     }
  2265. }
  2266.  
  2267. static __inline__ void pfield_orword_hires_h(int data, unsigned char *dp, int bit)
  2268. {
  2269.     ULONG *pixptr = (ULONG *)dp;
  2270.  
  2271.     *pixptr |= hirestab_h[data >> 8][0] << bit;
  2272.     *(pixptr+1) |= hirestab_h[data >> 8][1] << bit;
  2273.     *(pixptr+2) |= hirestab_h[data & 255][0] << bit;
  2274.     *(pixptr+3) |= hirestab_h[data & 255][1] << bit;
  2275. }
  2276.  
  2277. static __inline__ void pfield_orword_lores_h(int data, unsigned char *dp, int bit)
  2278. {
  2279.     ULONG *pixptr = (ULONG *)dp;
  2280.  
  2281.     *pixptr |= lorestab_h[data >> 8][0] << bit;
  2282.     *(pixptr+1) |= lorestab_h[data >> 8][1] << bit;
  2283.     *(pixptr+2) |= lorestab_h[data >> 8][2] << bit;
  2284.     *(pixptr+3) |= lorestab_h[data >> 8][3] << bit;
  2285.     *(pixptr+4) |= lorestab_h[data & 255][0] << bit;
  2286.     *(pixptr+5) |= lorestab_h[data & 255][1] << bit;
  2287.     *(pixptr+6) |= lorestab_h[data & 255][2] << bit;
  2288.     *(pixptr+7) |= lorestab_h[data & 255][3] << bit;
  2289. }
  2290.  
  2291. static __inline__ void pfield_setword_hires_h(int data, unsigned char *dp, int bit)
  2292. {
  2293.     ULONG *pixptr = (ULONG *)dp;
  2294.  
  2295.     *pixptr = hirestab_h[data >> 8][0] << bit;
  2296.     *(pixptr+1) = hirestab_h[data >> 8][1] << bit;
  2297.     *(pixptr+2) = hirestab_h[data & 255][0] << bit;
  2298.     *(pixptr+3) = hirestab_h[data & 255][1] << bit;
  2299. }
  2300.  
  2301. static __inline__ void pfield_setword_lores_h(int data, unsigned char *dp, int bit)
  2302. {
  2303.     ULONG *pixptr = (ULONG *)dp;
  2304.  
  2305.     *pixptr = lorestab_h[data >> 8][0] << bit;
  2306.     *(pixptr+1) = lorestab_h[data >> 8][1] << bit;
  2307.     *(pixptr+2) = lorestab_h[data >> 8][2] << bit;
  2308.     *(pixptr+3) = lorestab_h[data >> 8][3] << bit;
  2309.     *(pixptr+4) = lorestab_h[data & 255][0] << bit;
  2310.     *(pixptr+5) = lorestab_h[data & 255][1] << bit;
  2311.     *(pixptr+6) = lorestab_h[data & 255][2] << bit;
  2312.     *(pixptr+7) = lorestab_h[data & 255][3] << bit;
  2313. }
  2314.  
  2315. static __inline__ void pfield_orword_hires_l(int data, unsigned char *dp, int bit)
  2316. {
  2317.     ULONG *pixptr = (ULONG *)dp;
  2318.  
  2319.     *pixptr |= hirestab_l[data >> 8][0] << bit;
  2320.     *(pixptr+1) |= hirestab_l[data & 255][0] << bit;
  2321. }
  2322.  
  2323. static __inline__ void pfield_orword_lores_l(int data, unsigned char *dp, int bit)
  2324. {
  2325.     ULONG *pixptr = (ULONG *)dp;
  2326.  
  2327.     *pixptr |= lorestab_l[data >> 8][0] << bit;
  2328.     *(pixptr+1) |= lorestab_l[data >> 8][1] << bit;
  2329.     *(pixptr+2) |= lorestab_l[data & 255][0] << bit;
  2330.     *(pixptr+3) |= lorestab_l[data & 255][1] << bit;
  2331. }
  2332.  
  2333. static __inline__ void pfield_setword_hires_l(int data, unsigned char *dp, int bit)
  2334. {
  2335.     ULONG *pixptr = (ULONG *)dp;
  2336.  
  2337.     *pixptr = hirestab_l[data >> 8][0] << bit;
  2338.     *(pixptr+1) = hirestab_l[data & 255][0] << bit;
  2339. }
  2340.  
  2341. static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int bit)
  2342. {
  2343.     ULONG *pixptr = (ULONG *)dp;
  2344.  
  2345.     *pixptr = lorestab_l[data >> 8][0] << bit;
  2346.     *(pixptr+1) = lorestab_l[data >> 8][1] << bit;
  2347.     *(pixptr+2) = lorestab_l[data & 255][0] << bit;
  2348.     *(pixptr+3) = lorestab_l[data & 255][1] << bit;
  2349. }
  2350.  
  2351. #define DO_ONE_PLANE(POINTER, MULT, FUNC, DELAY, LL_SUB, P_ADD) { \
  2352.     int i; \
  2353.     unsigned int bpldat1; \
  2354.     UWORD data; \
  2355.     unsigned int bpldat2 = 0; \
  2356.     for (i = plflinelen; i > 0; i -= LL_SUB) { \
  2357.         bpldat1 = bpldat2; \
  2358.     bpldat2 = *POINTER++; \
  2359.     data = (bpldat1 << (16 - DELAY)) | (bpldat2 >> DELAY); \
  2360.     FUNC(data, app, MULT); \
  2361.     app += P_ADD; \
  2362.     } \
  2363.     data = bpldat2 << (16 - DELAY); \
  2364.     FUNC(data, app, MULT); \
  2365. }
  2366.  
  2367. #define DO_ONE_PLANE_B_LORES_H(NUM, FETCH) \
  2368.         if (bplplanecnt > NUM) { \
  2369.                     if (FETCH != 0) { \
  2370.             plfd[NUM] <<= 16; \
  2371.             if (FETCH == 1) \
  2372.                 plfd[NUM] |= *(r_bplpt[NUM])++ << delay[NUM & 1]; \
  2373.             d = plfd[NUM] >> 24; \
  2374.                     } else {\
  2375.             d = (plfd[NUM] >> 16) & 255; \
  2376.             }\
  2377.             if (NUM == 0) { \
  2378.             data1 = lorestab_h[d][0] << NUM;\
  2379.             data2 = lorestab_h[d][1] << NUM;\
  2380.             data3 = lorestab_h[d][2] << NUM;\
  2381.             data4 = lorestab_h[d][3] << NUM;\
  2382.             } else { \
  2383.             data1 |= lorestab_h[d][0] << NUM;\
  2384.             data2 |= lorestab_h[d][1] << NUM;\
  2385.             data3 |= lorestab_h[d][2] << NUM;\
  2386.             data4 |= lorestab_h[d][3] << NUM;\
  2387.             } \
  2388.         }
  2389.  
  2390. #if 1
  2391. static void pfield_doline_h(void)
  2392. {
  2393.     int xpos = plfstrt * 4 - 0x60;
  2394.     int spr;
  2395.  
  2396.     if (bplhires) {
  2397.     if (bplplanecnt > 0) {
  2398.         int xpos1 = xpos + 16 + (bpldelay1 >= 8 ? 16 : 0);
  2399.         int xpos2 = xpos + 16 + (bpldelay2 >= 8 ? 16 : 0);
  2400.         int delay1 = 2*(bpldelay1 & 7);
  2401.         int delay2 = 2*(bpldelay2 & 7);
  2402.         unsigned char *app = pixdata.apixels + xpos1;
  2403.  
  2404.         DO_ONE_PLANE(r_bplpt[0], 0, pfield_setword_hires_h, delay1, 4, 16);
  2405.         if (bplplanecnt > 2) {
  2406.         app = pixdata.apixels + xpos1;
  2407.         DO_ONE_PLANE(r_bplpt[2], 2, pfield_orword_hires_h, delay1, 4, 16);
  2408.         }
  2409. #if AGA_CHIPSET == 1
  2410.         if (bplplanecnt > 4) {
  2411.         app = pixdata.apixels + xpos1;
  2412.         DO_ONE_PLANE(r_bplpt[4], 4, pfield_orword_hires_h, delay1, 4, 16);
  2413.         }
  2414.         if (bplplanecnt > 6) {
  2415.         app = pixdata.apixels + xpos1;
  2416.         DO_ONE_PLANE(r_bplpt[6], 6, pfield_orword_hires_h, delay1, 4, 16);
  2417.         }
  2418. #endif
  2419.         if (bplplanecnt > 1) {
  2420.         app = pixdata.apixels + xpos2;
  2421.         DO_ONE_PLANE(r_bplpt[1], 1, pfield_orword_hires_h, delay2, 4, 16);
  2422.         }
  2423.         if (bplplanecnt > 3) {
  2424.         app = pixdata.apixels + xpos2;
  2425.         DO_ONE_PLANE(r_bplpt[3], 3, pfield_orword_hires_h, delay2, 4, 16);
  2426.         }
  2427. #if AGA_CHIPSET == 1
  2428.         if (bplplanecnt > 5) {
  2429.         app = pixdata.apixels + xpos2;
  2430.         DO_ONE_PLANE(r_bplpt[5], 5, pfield_orword_hires_h, delay2, 4, 16);
  2431.         }
  2432.         if (bplplanecnt > 7) {
  2433.         app = pixdata.apixels + xpos2;
  2434.         DO_ONE_PLANE(r_bplpt[7], 7, pfield_orword_hires_h, delay2, 4, 16);
  2435.         }
  2436. #endif
  2437.     } else {
  2438.         memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
  2439.     }
  2440.     } else {
  2441.     if (bplplanecnt > 0) {
  2442.         int x = xpos + 32;
  2443.         unsigned char *app = pixdata.apixels + x;
  2444. #if 0 /* Fun things to do in the future */
  2445.         int delay[2];
  2446.         int len;
  2447.         ULONG plfd[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  2448.         ULONG *ptr = (ULONG *)app;
  2449.         ULONG d;
  2450.         ULONG data, data1, data2, data3, data4;
  2451.         delay[0] = 16 - bpldelay1; delay[1] = 16 - bpldelay2;
  2452.  
  2453.         for (len = plflinelen; len > 0; len -= 8, ptr+=8) {
  2454.         DO_ONE_PLANE_B_LORES_H(0,1);
  2455.         DO_ONE_PLANE_B_LORES_H(1,1);
  2456.         DO_ONE_PLANE_B_LORES_H(2,1);
  2457.         DO_ONE_PLANE_B_LORES_H(3,1);
  2458.         DO_ONE_PLANE_B_LORES_H(4,1);
  2459.         DO_ONE_PLANE_B_LORES_H(5,1);
  2460.         *ptr = data1; *(ptr+1) = data2; *(ptr+2) = data3; *(ptr+3) = data4;
  2461.         
  2462.         DO_ONE_PLANE_B_LORES_H(0,0);
  2463.         DO_ONE_PLANE_B_LORES_H(1,0);
  2464.         DO_ONE_PLANE_B_LORES_H(2,0);
  2465.         DO_ONE_PLANE_B_LORES_H(3,0);
  2466.         DO_ONE_PLANE_B_LORES_H(4,0);
  2467.         DO_ONE_PLANE_B_LORES_H(5,0);
  2468.         *(ptr+4) = data1; *(ptr+5) = data2; *(ptr+6) = data3; *(ptr+7) = data4;
  2469.         }
  2470.         DO_ONE_PLANE_B_LORES_H(0,2);
  2471.         DO_ONE_PLANE_B_LORES_H(1,2);
  2472.         DO_ONE_PLANE_B_LORES_H(2,2);
  2473.         DO_ONE_PLANE_B_LORES_H(3,2);
  2474.         DO_ONE_PLANE_B_LORES_H(4,2);
  2475.         DO_ONE_PLANE_B_LORES_H(5,2);
  2476.         *ptr = data1; *(ptr+1) = data2; *(ptr+2) = data3; *(ptr+3) = data4;
  2477.         
  2478.         DO_ONE_PLANE_B_LORES_H(0,0);
  2479.         DO_ONE_PLANE_B_LORES_H(1,0);
  2480.         DO_ONE_PLANE_B_LORES_H(2,0);
  2481.         DO_ONE_PLANE_B_LORES_H(3,0);
  2482.         DO_ONE_PLANE_B_LORES_H(4,0);
  2483.         DO_ONE_PLANE_B_LORES_H(5,0);
  2484.         *(ptr+4) = data1; *(ptr+5) = data2; *(ptr+6) = data3; *(ptr+7) = data4;
  2485. #else
  2486.         DO_ONE_PLANE(r_bplpt[0], 0, pfield_setword_lores_h, bpldelay1, 8, 32);
  2487.         if (bplplanecnt > 2) {
  2488.         app = pixdata.apixels + x;
  2489.         DO_ONE_PLANE(r_bplpt[2], 2, pfield_orword_lores_h, bpldelay1, 8, 32);
  2490.         }
  2491.         if (bplplanecnt > 4) {
  2492.         app = pixdata.apixels + x;
  2493.         DO_ONE_PLANE(r_bplpt[4], 4, pfield_orword_lores_h, bpldelay1, 8, 32);
  2494.         }
  2495. #if AGA_CHIPSET == 1
  2496.         if (bplplanecnt > 6) {
  2497.         app = pixdata.apixels + x;
  2498.         DO_ONE_PLANE(r_bplpt[6], 6, pfield_orword_lores_h, bpldelay1, 8, 32);
  2499.         }
  2500. #endif
  2501.         if (bplplanecnt > 1) {
  2502.         app = pixdata.apixels + x;
  2503.         DO_ONE_PLANE(r_bplpt[1], 1, pfield_orword_lores_h, bpldelay2, 8, 32);
  2504.         }
  2505.         if (bplplanecnt > 3) {
  2506.         app = pixdata.apixels + x;
  2507.         DO_ONE_PLANE(r_bplpt[3], 3, pfield_orword_lores_h, bpldelay2, 8, 32);
  2508.         }
  2509.         if (bplplanecnt > 5) {
  2510.         app = pixdata.apixels + x;
  2511.         DO_ONE_PLANE(r_bplpt[5], 5, pfield_orword_lores_h, bpldelay2, 8, 32);
  2512.         }
  2513. #if AGA_CHIPSET == 1
  2514.         if (bplplanecnt > 7) {
  2515.         app = pixdata.apixels + x;
  2516.         DO_ONE_PLANE(r_bplpt[7], 7, pfield_orword_lores_h, bpldelay2, 8, 32);
  2517.         }
  2518. #endif
  2519. #endif
  2520.     } else {
  2521.         memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
  2522.     }
  2523.     }
  2524.     
  2525.     linetoscreen = 1;
  2526.  
  2527.     for(spr = 7; spr >= 0; spr--) {
  2528.     if (bpl_info.sprarmed[spr]) {
  2529.         int sprxp = ((bpl_info.sprpos[spr] & 0xFF) * 4) - 0x60 + (bpl_info.sprctl[spr] & 1)*2;
  2530.         int i;
  2531.         /* Ugh. Nasty bug. Let's rather lose some sprites than trash
  2532.          * memory. */
  2533.         if (sprxp >= 0)
  2534.         pfield_sprite_h (spr, sprxp, bpl_info.sprdata[spr], bpl_info.sprdatb[spr]);
  2535.     }
  2536.     }
  2537. }
  2538. #endif
  2539. static void pfield_doline_l(void)
  2540. {
  2541.     int xpos = plfstrt * 2 - 0x30;
  2542.     int spr;
  2543.         
  2544.     if (bplhires) {
  2545.     if (bplplanecnt > 0) {
  2546.         int xpos1 = xpos + 8 + (bpldelay1 >= 8 ? 8 : 0);
  2547.         int xpos2 = xpos + 8 + (bpldelay2 >= 8 ? 8 : 0);
  2548.         int delay1 = (bpldelay1 & 7) * 2;
  2549.         int delay2 = (bpldelay2 & 7) * 2;
  2550.         unsigned char *app = pixdata.apixels + xpos1;
  2551.         
  2552.         DO_ONE_PLANE(r_bplpt[0], 0, pfield_setword_hires_l, delay1, 4, 8);
  2553.         if (bplplanecnt > 2) {
  2554.         app = pixdata.apixels + xpos1;
  2555.         DO_ONE_PLANE(r_bplpt[2], 2, pfield_orword_hires_l, delay1, 4, 8);
  2556.         }
  2557. #if AGA_CHIPSET == 1
  2558.         if (bplplanecnt > 4) {
  2559.         app = pixdata.apixels + xpos1;
  2560.         DO_ONE_PLANE(r_bplpt[4], 4, pfield_orword_hires_l, delay1, 4, 8);
  2561.         }
  2562.         if (bplplanecnt > 6) {
  2563.         app = pixdata.apixels + xpos1;
  2564.         DO_ONE_PLANE(r_bplpt[6], 6, pfield_orword_hires_l, delay1, 4, 8);
  2565.         }
  2566. #endif
  2567.         if (bplplanecnt > 1) {
  2568.         app = pixdata.apixels + xpos2;
  2569.         DO_ONE_PLANE(r_bplpt[1], 1, pfield_orword_hires_l, delay2, 4, 8);
  2570.         }
  2571.         if (bplplanecnt > 3) {
  2572.         app = pixdata.apixels + xpos2;
  2573.         DO_ONE_PLANE(r_bplpt[3], 3, pfield_orword_hires_l, delay2, 4, 8);
  2574.         }
  2575. #if AGA_CHIPSET == 1
  2576.         if (bplplanecnt > 5) {
  2577.         app = pixdata.apixels + xpos2;
  2578.         DO_ONE_PLANE(r_bplpt[5], 5, pfield_orword_hires_l, delay2, 4, 8);
  2579.         }
  2580.         if (bplplanecnt > 7) {
  2581.         app = pixdata.apixels + xpos2;
  2582.         DO_ONE_PLANE(r_bplpt[7], 7, pfield_orword_hires_l, delay2, 4, 8);
  2583.         }
  2584. #endif
  2585.     } else {
  2586.         memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
  2587.     }
  2588.     } else {
  2589.     if (bplplanecnt > 0) {
  2590.         int x = xpos + 16;
  2591.         int delay1 = bpldelay1;
  2592.         int delay2 = bpldelay2;
  2593.         unsigned char *app = pixdata.apixels + x;
  2594.         DO_ONE_PLANE(r_bplpt[0], 0, pfield_setword_lores_l, delay1, 8, 16);
  2595.         if (bplplanecnt > 2) {
  2596.         app = pixdata.apixels + x;
  2597.         DO_ONE_PLANE(r_bplpt[2], 2, pfield_orword_lores_l, delay1, 8, 16);
  2598.         }
  2599.         if (bplplanecnt > 4) {
  2600.         app = pixdata.apixels + x;
  2601.         DO_ONE_PLANE(r_bplpt[4], 4, pfield_orword_lores_l, delay1, 8, 16);
  2602.         }
  2603. #if AGA_CHIPSET == 1
  2604.         if (bplplanecnt > 6) {
  2605.         app = pixdata.apixels + x;
  2606.         DO_ONE_PLANE(r_bplpt[6], 6, pfield_orword_lores_l, delay1, 8, 16);
  2607.         }
  2608. #endif
  2609.         if (bplplanecnt > 1) {
  2610.         app = pixdata.apixels + x;
  2611.         DO_ONE_PLANE(r_bplpt[1], 1, pfield_orword_lores_l, delay2, 8, 16);
  2612.         }
  2613.         if (bplplanecnt > 3) {
  2614.         app = pixdata.apixels + x;
  2615.         DO_ONE_PLANE(r_bplpt[3], 3, pfield_orword_lores_l, delay2, 8, 16);
  2616.         }
  2617.         if (bplplanecnt > 5) {
  2618.         app = pixdata.apixels + x;
  2619.         DO_ONE_PLANE(r_bplpt[5], 5, pfield_orword_lores_l, delay2, 8, 16);
  2620.         }
  2621. #if AGA_CHIPSET == 1
  2622.         if (bplplanecnt > 7) {
  2623.         app = pixdata.apixels + x;
  2624.         DO_ONE_PLANE(r_bplpt[7], 7, pfield_orword_lores_l, delay2, 8, 16);
  2625.         }
  2626. #endif
  2627.     } else {
  2628.         memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
  2629.     }
  2630.     }
  2631.  
  2632.     linetoscreen = 1;
  2633.  
  2634.     for(spr = 7; spr >= 0; spr--) {
  2635.     if (bpl_info.sprarmed[spr]) {
  2636.         int sprxp = ((bpl_info.sprpos[spr] & 0xFF) * 2) - 0x30 + (bpl_info.sprctl[spr] & 1);
  2637.         int i;
  2638.         /* Ugh. Nasty bug. Let's rather lose some sprites than trash
  2639.          * memory. */
  2640.         if (sprxp >= 0)
  2641.         pfield_sprite_l (spr, sprxp, bpl_info.sprdata[spr], bpl_info.sprdatb[spr]);
  2642.     }
  2643.     }
  2644. }
  2645.  
  2646. static int bpl_data_differs(UWORD *data, UWORD *r_addr, int nbytes)
  2647. {
  2648.     return memcmpy(data, r_addr, nbytes);
  2649. }
  2650.  
  2651. static __inline__ int bplinfo_differs(struct bplinfo *a, struct bplinfo *b)
  2652. {
  2653.     int ncolors;
  2654.     int i;
  2655.     if (a->bplcon0 != b->bplcon0
  2656.     || a->bplcon1 != b->bplcon1
  2657.     || a->bplcon2 != b->bplcon2
  2658.     || a->bplcon3 != b->bplcon3
  2659.     || a->bplcon4 != b->bplcon4
  2660.     || a->diwstrt != b->diwstrt
  2661.     || a->diwstop != b->diwstop
  2662.     || a->ddfstrt != b->ddfstrt
  2663.     || a->ddfstop != b->ddfstop)
  2664.     return 1;
  2665.  
  2666. #if 1
  2667.     /* This sometimes loses for sprite colors */
  2668.     ncolors = 1 << ((a->bplcon0 & 0x7000) >> 12);
  2669.     if (ncolors == 64)
  2670.     ncolors = (a->bplcon0 & 0x800) ? 16 : 32;
  2671.     for (i = 0; i < ncolors; i++)
  2672.     if (a->color_regs[i] != b->color_regs[i])
  2673.         return 1;
  2674. #else
  2675.     /* ... and this will lose badly on few-color screens when we implement 
  2676.      * AGA.
  2677.      */
  2678.     if (memcmp(a->color_regs, b->color_regs, sizeof a->color_regs) != 0)
  2679.     return 1;
  2680. #endif
  2681.     for (i = 0; i < 8; i++) {
  2682.     if (a->sprarmed[i] != b->sprarmed[i])
  2683.         return 1;
  2684.     if (a->sprarmed[i]
  2685.         && (a->sprctl[i] != b->sprctl[i]
  2686.         || a->sprpos[i] != b->sprpos[i]
  2687.         || a->sprdata[i] != b->sprdata[i]
  2688.         || a->sprdatb[i] != b->sprdatb[i]))
  2689.         return 1;
  2690.     }
  2691.     return 0;
  2692. }
  2693.  
  2694. static void pfield_doline(void)
  2695. {
  2696.     int bytecount = plflinelen / (bplhires ? 4 : 8) * 2;
  2697.     int drawit = 0;
  2698.     int i;
  2699.     
  2700.     if (vpos < plffirstline || vpos >= plflastline) 
  2701.         return;
  2702.  
  2703.     if (!dmaen(0x100) || !pfield_linedmaon) {
  2704.     line_in_border = 1;
  2705.     return;
  2706.     }
  2707.     
  2708.     for (i = 0; i < bplplanecnt; i++) {
  2709.     r_bplpt[i] = pfield_xlateptr(bplpt[i], bytecount);
  2710.     if (r_bplpt[i] == NULL)
  2711.         return;
  2712.     }
  2713.     
  2714. #if SMART_UPDATE == 1
  2715.     drawit = bplinfo_differs(&bpl_info, &linedescr[next_lineno].bpl_info);
  2716.     if (drawit) {
  2717.     linedescr[next_lineno].bpl_info = bpl_info;
  2718.     }
  2719.     drawit |= !linedescr[next_lineno].linedata_valid;
  2720.     
  2721.     if (bytecount <= MAX_WORDS_PER_LINE * 2) {
  2722.     linedescr[next_lineno].linedata_valid = 1;
  2723.     for (i = 0; i < bplplanecnt; i++)
  2724.         drawit |= bpl_data_differs(line_data[next_lineno][i],r_bplpt[i],
  2725.                        bytecount);
  2726.     
  2727.     } else {
  2728.     linedescr[next_lineno].linedata_valid = 0;
  2729.     }
  2730. #endif
  2731.  
  2732.     pfield_modulos(bytecount);
  2733.  
  2734. #if SMART_UPDATE != 0
  2735.     if (!drawit)
  2736.     return;
  2737. #endif    
  2738.  
  2739.     if (use_lores)
  2740.     pfield_doline_l();
  2741.     else
  2742.     pfield_doline_h();
  2743. }
  2744.  
  2745. static void pfield_doline_slow(int currhp)
  2746. {
  2747.     if (vpos < plffirstline || vpos >= plflastline) 
  2748.         return;
  2749.     
  2750.     if (currhp == plfstrt)
  2751.     slowline_nextpos = currhp;
  2752.  
  2753.     if (currhp == slowline_nextpos) {    
  2754.     if (slowline_linepos >= plflinelen) {
  2755.         pfield_modulos(0);
  2756.         slowline_nextpos = -1;
  2757.     } else {
  2758.         slowline_nextpos += bplhires ? 4 : 8;
  2759.         slowline_linepos += bplhires ? 4 : 8;
  2760.  
  2761.         pfield_fetchdata();
  2762.  
  2763.         if (use_lores)
  2764.         pfield_doline_slow_l(currhp);
  2765.         else
  2766.         pfield_doline_slow_h(currhp);
  2767.     }
  2768.     }
  2769.     if (currhp > 48) {
  2770.     int xpos = PIXEL_XPOS(currhp);
  2771.     int spr;
  2772.     for(spr = 7; spr >= 0; spr--) {
  2773.         if (bpl_info.sprarmed[spr] && currhp == (bpl_info.sprpos[spr] & 0xFF)) {
  2774.         if (use_lores) {
  2775.             int sprxp = xpos + (bpl_info.sprctl[spr] & 1);
  2776.             pfield_sprite_l (spr, sprxp, bpl_info.sprdata[spr], bpl_info.sprdatb[spr]);
  2777.         } else {
  2778.             int sprxp = xpos + (bpl_info.sprctl[spr] & 1)*2;
  2779.             pfield_sprite_h (spr, sprxp, bpl_info.sprdata[spr], bpl_info.sprdatb[spr]);
  2780.         }
  2781.         }
  2782.     }
  2783.     }    
  2784. }
  2785.  
  2786. static void setdontcare(void)
  2787. {
  2788.     fprintf(stderr, "Don't care mouse mode set\n");
  2789.     mousestate=dont_care_mouse;
  2790.     lastspr0x=lastmx; lastspr0y=lastmy;
  2791.     mstepx=defstepx; mstepy=defstepy;
  2792. }
  2793.  
  2794. static void setfollow(void)
  2795. {
  2796.     fprintf(stderr, "Follow sprite mode set\n");
  2797.     mousestate=follow_mouse;
  2798.     lastdiffx=lastdiffy=0;
  2799.     sprvbfl=0;
  2800.     spr0ctl=spr0pos=0;
  2801.     mstepx=defstepx; mstepy=defstepy;
  2802. }
  2803.  
  2804. void togglemouse(void)
  2805. {
  2806.     switch(mousestate) {
  2807.      case dont_care_mouse: setfollow(); break;
  2808.      case follow_mouse: setdontcare(); break;
  2809.      default: break; /* Nnnnnghh! */
  2810.     }
  2811. }        
  2812.  
  2813. static __inline__ int adjust(int val)
  2814. {
  2815.     if (val>127)
  2816.     return 127; 
  2817.     else if (val<-127)
  2818.     return -127;
  2819.     return val;
  2820. }
  2821.  
  2822. static int first_drawn_line, last_drawn_line;
  2823. static int first_block_line, last_block_line;
  2824.  
  2825. static void init_frame (void)
  2826. {
  2827.     int i;
  2828.     int maxpos = use_lores ? 400 : 800;
  2829.     
  2830.     if (max_diwstop == 0)
  2831.     max_diwstop = diwlastword;
  2832.     
  2833.     if (max_diwstop < (use_lores ? 320 : 640) || max_diwstop > maxpos)
  2834.     prev_max_diwstop = maxpos;
  2835.     else
  2836.     prev_max_diwstop = max_diwstop;
  2837.  
  2838.     max_diwstop = 0;
  2839.  
  2840.     memset(spron, 0, sizeof spron);
  2841.     memset(bpl_info.sprpos, 0, sizeof bpl_info.sprpos);
  2842.     memset(bpl_info.sprctl, 0, sizeof bpl_info.sprctl);
  2843.     last_drawn_line = 0;
  2844.     first_drawn_line = 32767;
  2845.  
  2846.     first_block_line = last_block_line = -2;
  2847. }
  2848.  
  2849. static void do_flush_line (int lineno)
  2850. {
  2851.     if (lineno < first_drawn_line)
  2852.     first_drawn_line = lineno;
  2853.     if (lineno > last_drawn_line)
  2854.     last_drawn_line = lineno;
  2855.  
  2856.     if (gfxvidinfo.maxblocklines == 0)
  2857.     flush_line(lineno);
  2858.     else {
  2859.     if ((last_block_line+1) != lineno) {
  2860.         if (first_block_line != -2)
  2861.         flush_block (first_block_line, last_block_line);
  2862.         first_block_line = lineno;
  2863.     }
  2864.     last_block_line = lineno;
  2865.     if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
  2866.         flush_block (first_block_line, last_block_line);
  2867.         first_block_line = last_block_line = -2;
  2868.     }
  2869.     }
  2870. }
  2871.  
  2872. static void do_flush_screen (int start, int stop)
  2873. {
  2874.     if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) {
  2875.     flush_block (first_block_line, last_block_line);
  2876.     }
  2877.     if (start <= stop)
  2878.     flush_screen (start, stop);
  2879. }
  2880.  
  2881. static void vsync_handler(void)
  2882. {
  2883.     int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1);
  2884.     int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1;
  2885.     int diffx, diffy;
  2886.     int i;
  2887.     UWORD dir;
  2888.     int button;
  2889.  
  2890.     handle_events();
  2891.     getjoystate(&joy0dir, &joy0button);
  2892.  
  2893.     switch (mousestate) {
  2894.      case normal_mouse:
  2895.     diffx = lastmx - lastsampledmx;
  2896.     diffy = lastmy - lastsampledmy;
  2897.     if (!newmousecounters) {    
  2898.         if (diffx > 127) diffx = 127;
  2899.         if (diffx < -127) diffx = -127;
  2900.         joy0x += diffx;
  2901.         if (diffy > 127) diffy = 127;
  2902.         if (diffy < -127) diffy = -127;
  2903.         joy0y += diffy;
  2904.     }
  2905.     lastsampledmx += diffx; lastsampledmy += diffy;
  2906.     break;
  2907.  
  2908.      case dont_care_mouse:
  2909.     diffx = adjust (((lastmx-lastspr0x) * mstepx) >> 16);
  2910.     diffy = adjust (((lastmy-lastspr0y) * mstepy) >> 16);
  2911.     lastspr0x=lastmx; lastspr0y=lastmy;
  2912.     joy0x+=diffx; joy0y+=diffy;
  2913.     break;
  2914.     
  2915.      case follow_mouse:
  2916.     if (sprvbfl && sprvbfl-- >1) {
  2917.         int mousexpos, mouseypos;
  2918.         
  2919.         if ((lastdiffx > docal || lastdiffx < -docal) && lastspr0x != spr0x 
  2920.         && spr0x > plfstrt*4+34+xcaloff && spr0x < plfstop*4-xcaloff)
  2921.         {  
  2922.         int val = (lastdiffx << 16) / (spr0x - lastspr0x);
  2923.         if (val>=0x8000) mstepx=(mstepx*(calweight-1)+val)/calweight;
  2924.         }
  2925.         if ((lastdiffy > docal || lastdiffy < -docal) && lastspr0y != spr0y
  2926.         && spr0y>plffirstline+ycaloff && spr0y<plflastline-ycaloff) 
  2927.         { 
  2928.         int val = (lastdiffy<<16) / (spr0y-lastspr0y);
  2929.         if (val>=0x8000) mstepy=(mstepy*(calweight-1)+val)/calweight;
  2930.         }
  2931.         mousexpos = lastmx;
  2932.         mouseypos = lastmy;
  2933.         
  2934.         if(dont_want_aspect)
  2935.             mouseypos *= 2;
  2936.         if(use_lores)
  2937.             mousexpos = 2 * (mousexpos + prev_max_diwstop - 328);
  2938.  
  2939.         diffx = adjust ((((mousexpos + 0x70 + xoffs - spr0x) & ~1) * mstepx) >> 16);
  2940.         diffy = adjust ((((mouseypos + yoffs - spr0y+minfirstline*2) & ~1) * mstepy) >> 16);
  2941.         lastspr0x=spr0x; lastspr0y=spr0y;
  2942.         lastdiffx=diffx; lastdiffy=diffy;
  2943.         joy0x+=diffx; joy0y+=diffy; 
  2944.     }
  2945.     break;
  2946.     }
  2947.  
  2948.     INTREQ(0x8020);
  2949.     if (bpl_info.bplcon0 & 4) lof ^= 0x8000;
  2950.     COPJMP1(0);
  2951.     
  2952.     if (framecnt == 0)
  2953.         do_flush_screen (first_drawn_line, last_drawn_line);
  2954.  
  2955.     count_frame();
  2956.     init_frame();
  2957. #ifdef HAVE_GETTIMEOFDAY
  2958.     {
  2959.     struct timeval tv;
  2960.     unsigned long int newtime;
  2961.     
  2962.     gettimeofday(&tv,NULL);    
  2963.     newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000;
  2964.     
  2965.     if (!bogusframe) {    
  2966.         frametime += newtime - msecs;
  2967.         timeframes++;
  2968.     }
  2969.     msecs = newtime;
  2970.     bogusframe = 0;
  2971.     }
  2972. #endif
  2973.     CIA_vsync_handler();
  2974. }
  2975.  
  2976. static void hsync_handler(void)
  2977. {
  2978.     int lineno = vpos - minfirstline;
  2979.     int lineisdouble = 0;
  2980.     
  2981.     do_sprites(vpos, maxhpos);
  2982.     last_sprite = 0;
  2983.     
  2984.     if (!dont_want_aspect) {
  2985.     lineno *= 2;
  2986.     if (bpl_info.bplcon0 & 4) {
  2987.         if(!lof) {
  2988.         lineno++;
  2989.         }
  2990.     } else {
  2991.         lineisdouble = 1;
  2992.     }
  2993.     }
  2994.     
  2995.     if (disk_int_defer)
  2996.     if (!--disk_int_defer)
  2997.         INTREQ(0x8002);
  2998.     
  2999.     eventtab[ev_hsync].oldcycles = cycles;
  3000.     CIA_hsync_handler();
  3001.     
  3002.     if(produce_sound)
  3003.     do_sound ();
  3004.  
  3005.     if (framecnt == 0 && vpos >= minfirstline) {
  3006.     if (vpos >= plffirstline && vpos < plflastline)
  3007.     {
  3008.         /* Finish the line, if we started doing it with the slow update.
  3009.          * Otherwise, draw it entirely. */
  3010.         if (pfield_fullline) {        
  3011.         if (!pfield_linedone) {
  3012.             /* This can turn on line_in_border if DMA is off */
  3013.             pfield_doline();
  3014.         }
  3015.         if (linetoscreen)
  3016.             pfield_slow_linetoscr(0, maxhpos);
  3017.         } else {
  3018.         int i;
  3019.         for(i = pfield_lastpart_hpos; i < maxhpos; i++)
  3020.             pfield_doline_slow(i);
  3021.         pfield_slow_linetoscr(slowline_lasttoscr, maxhpos);
  3022.         /* The COLOR routine masks off the high nibble. This means
  3023.          * that there will never be 0xFFFF in color_regs[0], and this
  3024.          * means that the line will be drawn completely the next time
  3025.          * we get into pfield_doline()
  3026.          */
  3027.         linedescr[lineno].bpl_info.color_regs[0] = 0xFFFF;
  3028.         linetoscreen = 1;
  3029.         }
  3030.     } else
  3031.         line_in_border = 1;
  3032.     
  3033.     if (line_in_border && 
  3034.         (!linedescr[lineno].inborder 
  3035.          || linedescr[lineno].bordercol != acolors[0]))
  3036.     {
  3037.         linedescr[lineno].bordercol = acolors[0];
  3038.         linedescr[lineno].linedata_valid = 0;
  3039.         
  3040.         fill_line (lineno);
  3041.         linetoscreen = 1;
  3042.     }
  3043.         
  3044.     linedescr[lineno].inborder = line_in_border;
  3045.     
  3046.     if (linetoscreen) {
  3047.         do_flush_line (lineno);
  3048.     }
  3049.     if (lineisdouble) {
  3050.         int drawit = 0;
  3051.         
  3052.         if (linedescr[lineno].inborder != linedescr[lineno+1].inborder
  3053.         || (linedescr[lineno].inborder == 1
  3054.             && linedescr[lineno].bordercol != linedescr[lineno+1].bordercol)) {
  3055.         drawit = 1;
  3056.         
  3057.         } else if (linedescr[lineno].inborder == 0 
  3058.                && (linetoscreen 
  3059.                || (bplinfo_differs(&linedescr[lineno].bpl_info, 
  3060.                            &linedescr[lineno+1].bpl_info)))) {
  3061.         drawit = 1;
  3062.         }
  3063.         
  3064.         if (drawit) {
  3065.         linedescr[lineno+1].inborder = linedescr[lineno].inborder;
  3066.         linedescr[lineno+1].bordercol = linedescr[lineno].bordercol;
  3067. #if SMART_UPDATE != 0
  3068.         linedescr[lineno+1].bpl_info = linedescr[lineno].bpl_info;
  3069. #endif
  3070.         memcpy (gfxvidinfo.bufmem + (lineno+1)*gfxvidinfo.rowbytes,
  3071.             gfxvidinfo.bufmem + lineno*gfxvidinfo.rowbytes,
  3072.             gfxvidinfo.rowbytes);
  3073.         do_flush_line (lineno+1);
  3074.         }
  3075.     }
  3076.     }
  3077.  
  3078.     pfield_calclinedma();
  3079.  
  3080.     if (++vpos == (maxvpos + (lof != 0))) {
  3081.     vpos = 0;
  3082.     vsync_handler();
  3083.     }
  3084.     
  3085.     if (framecnt == 0) 
  3086.     {
  3087.     lineno = vpos - minfirstline;
  3088.     
  3089.     if (!dont_want_aspect) {
  3090.         lineno *= 2;
  3091.         if ((bpl_info.bplcon0 & 4) && !lof) {
  3092.         lineno++;
  3093.         }
  3094.     }
  3095.     xlinebuffer = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * lineno;
  3096.     aga_lbufptr = aga_linebuf;
  3097.     next_lineno = lineno;
  3098.     linetoscreen = 0;
  3099.     line_in_border = 0;
  3100.     pfield_fullline = 1;
  3101.     pfield_linedone = 0;
  3102.     pfield_lastpart_hpos = 0;
  3103.     }
  3104.  
  3105. }
  3106.  
  3107. void customreset(void)
  3108. {
  3109.     int i;
  3110. #ifdef HAVE_GETTIMEOFDAY
  3111.     struct timeval tv;
  3112. #endif
  3113.     inhibit_frame = 0;
  3114.     expamem_reset();
  3115.     CIA_reset();
  3116.     cycles = 0; 
  3117.     specialflags = 0;
  3118.     
  3119.     last_sprite = 0;
  3120.     vpos = 0; 
  3121.     lof = 0;
  3122.     next_lineno = 0;
  3123.     max_diwstop = 0;
  3124.     
  3125.     if (needmousehack()) {
  3126.         if (mousestate != follow_mouse) setfollow();
  3127.     } else {
  3128.     mousestate = normal_mouse;
  3129.     }
  3130.  
  3131.     memset(spixels, 0, sizeof(spixels));
  3132.     memset(spixstate, 0, sizeof(spixstate));
  3133.     
  3134.     /*memset(blitcount, 0, sizeof(blitcount));  blitter debug */
  3135.     
  3136.     for (i = 0; i < numscrlines*2; i++) {
  3137.     linedescr[i].mnn = NULL;
  3138.     linedescr[i].linedata_valid = 0;
  3139.     linedescr[i].bpl_info.color_regs[0] = 0xFFFF;
  3140.     linedescr[i].bplpt[0] = (CPTR)-1;
  3141.     }
  3142.     
  3143.     xlinebuffer = gfxvidinfo.bufmem;
  3144.  
  3145.     dmacon = intena = 0;
  3146.     bltstate = BLT_done;
  3147.     copstate = COP_stop;
  3148.     copcon = 0;
  3149.     dskdmaen = 0;
  3150.     cycles = 0;
  3151.     for(i = 0; i < ev_max; i++) {
  3152.     eventtab[i].active = 0;
  3153.     eventtab[i].oldcycles = 0;
  3154.     }
  3155.     copper_active = 0;
  3156.     eventtab[ev_cia].handler = CIA_handler;
  3157.     eventtab[ev_copper].handler = do_copper;
  3158.     eventtab[ev_hsync].handler = hsync_handler;
  3159.     eventtab[ev_hsync].evtime = maxhpos;
  3160.     eventtab[ev_hsync].active = 1;
  3161. #ifdef DEFERRED_INT
  3162.     eventtab[ev_deferint].handler = defer_int_handler;
  3163.     eventtab[ev_deferint].active = 0;
  3164. #endif
  3165.     events_schedule();
  3166.     
  3167.     init_frame();
  3168. #ifdef HAVE_GETTIMEOFDAY
  3169.     gettimeofday(&tv,NULL);
  3170.     seconds_base = tv.tv_sec;
  3171.     bogusframe = 1;
  3172. #endif
  3173. }
  3174.  
  3175. void dumpcustom(void)
  3176. {
  3177.     int i;
  3178.     fprintf(stderr, "DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(),
  3179.        intena, intreq, vpos, current_hpos());
  3180.     if (timeframes) { 
  3181.     fprintf(stderr, "Average frame time: %d ms [frames: %d time: %d]\n", 
  3182.            frametime/timeframes, timeframes, frametime);
  3183.     }
  3184.     /*for (i=0; i<256; i++) if (blitcount[i]) fprintf(stderr, "minterm %x = %d\n",i,blitcount[i]);  blitter debug */
  3185. }
  3186.  
  3187. int intlev(void)
  3188. {
  3189.     UWORD imask = intreq & intena;
  3190.     if (imask && (intena & 0x4000)){
  3191.     if (imask & 0x2000) return 6;
  3192.     if (imask & 0x1800) return 5;
  3193.     if (imask & 0x0780) return 4;
  3194.     if (imask & 0x0070) return 3;
  3195.     if (imask & 0x0008) return 2;
  3196.     if (imask & 0x0007) return 1;
  3197.     }
  3198.     return -1;
  3199. }
  3200.  
  3201. void custom_init(void)
  3202. {
  3203.     int num;
  3204.     if (needmousehack())
  3205.     setfollow();
  3206.     customreset();
  3207.     for (num = 0; num < 256; num++) {    
  3208.     int plane1 = (num & 1) | ((num >> 1) & 2) | ((num >> 2) & 4) | ((num >> 3) & 8);
  3209.     int plane2 = ((num >> 1) & 1) | ((num >> 2) & 2) | ((num >> 3) & 4) | ((num >> 4) & 8);
  3210.     dblpf_2nd1[num] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1;
  3211.     dblpf_2nd2[num] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2;
  3212.     dblpf_aga1[num] = plane1 == 0 ? plane2 : plane1;
  3213.     dblpf_aga2[num] = plane2 == 0 ? plane1 : plane2;
  3214.     if (plane2 > 0) plane2 += 8;
  3215.     dblpf_ind1[num] = plane1 == 0 ? plane2 : plane1;
  3216.     dblpf_ind2[num] = plane2 == 0 ? plane1 : plane2;
  3217.     }
  3218.     build_filltable();
  3219.     gen_pfield_tables();
  3220. }
  3221.  
  3222. /* Custom chip memory bank */
  3223.  
  3224. static ULONG custom_lget(CPTR) REGPARAM;
  3225. static UWORD custom_wget(CPTR) REGPARAM;
  3226. static UBYTE custom_bget(CPTR) REGPARAM;
  3227. static void  custom_lput(CPTR, ULONG) REGPARAM;
  3228. static void  custom_wput(CPTR, UWORD) REGPARAM;
  3229. static void  custom_bput(CPTR, UBYTE) REGPARAM;
  3230.  
  3231. addrbank custom_bank = {
  3232.     custom_lget, custom_wget, custom_bget,
  3233.     custom_lput, custom_wput, custom_bput,
  3234.     default_xlate, default_check
  3235. };
  3236.  
  3237. UWORD custom_wget(CPTR addr)
  3238. {
  3239.     switch(addr & 0x1FE) {
  3240.      case 0x002: return DMACONR();
  3241.      case 0x004: return VPOSR();
  3242.      case 0x006: return VHPOSR();
  3243.     
  3244.      case 0x008: return DSKDATR();
  3245.      case 0x012: return POT0DAT();
  3246.      case 0x016: return POTGOR();
  3247.      case 0x018: return SERDATR();
  3248.      case 0x01A: return DSKBYTR();
  3249.      case 0x01C: return INTENAR();
  3250.      case 0x01E: return INTREQR();
  3251.      case 0x010: return ADKCONR();
  3252.      case 0x00A: return JOY0DAT();
  3253.      case 0x00C: return JOY1DAT();
  3254. #ifdef ECS_DENISE
  3255.      case 0x07C: return 0xFC;
  3256. #endif
  3257.      default:
  3258.     custom_wput(addr,0);
  3259.     return 0xffff;
  3260.     }
  3261. }
  3262.  
  3263. UBYTE custom_bget(CPTR addr)
  3264. {
  3265.     return custom_wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8);
  3266. }
  3267.  
  3268. ULONG custom_lget(CPTR addr)
  3269. {
  3270.     return ((ULONG)custom_wget(addr & 0xfffe) << 16) | custom_wget((addr+2) & 0xfffe);
  3271. }
  3272.  
  3273. void custom_wput(CPTR addr, UWORD value)
  3274. {
  3275.     addr &= 0x1FE;
  3276.     cregs[addr>>1] = value;
  3277.     switch(addr) {    
  3278.      case 0x020: DSKPTH(value); break;
  3279.      case 0x022: DSKPTL(value); break;
  3280.      case 0x024: DSKLEN(value); break;
  3281.      case 0x026: DSKDAT(value); break;
  3282.     
  3283.      case 0x02A: VPOSW(value); break;
  3284.     
  3285.      case 0x040: BLTCON0(value); break;
  3286.      case 0x042: BLTCON1(value); break;
  3287.     
  3288.      case 0x044: BLTAFWM(value); break;
  3289.      case 0x046: BLTALWM(value); break;
  3290.     
  3291.      case 0x050: BLTAPTH(value); break;
  3292.      case 0x052: BLTAPTL(value); break;
  3293.      case 0x04C: BLTBPTH(value); break;
  3294.      case 0x04E: BLTBPTL(value); break;
  3295.      case 0x048: BLTCPTH(value); break;
  3296.      case 0x04A: BLTCPTL(value); break;
  3297.      case 0x054: BLTDPTH(value); break;
  3298.      case 0x056: BLTDPTL(value); break;
  3299.     
  3300.      case 0x058: BLTSIZE(value); break;
  3301.     
  3302.      case 0x064: BLTAMOD(value); break;
  3303.      case 0x062: BLTBMOD(value); break;
  3304.      case 0x060: BLTCMOD(value); break;
  3305.      case 0x066: BLTDMOD(value); break;
  3306.     
  3307.      case 0x070: BLTCDAT(value); break;
  3308.      case 0x072: BLTBDAT(value); break;
  3309.      case 0x074: BLTADAT(value); break;
  3310.             
  3311.      case 0x07E: DSKSYNC(value); break;
  3312.  
  3313.      case 0x080: COP1LCH(value); break;
  3314.      case 0x082: COP1LCL(value); break;
  3315.      case 0x084: COP2LCH(value); break;
  3316.      case 0x086: COP2LCL(value); break;
  3317.     
  3318.      case 0x088: COPJMP1(value); break;
  3319.      case 0x08A: COPJMP2(value); break;
  3320.     
  3321.      case 0x08E: DIWSTRT(value); break;
  3322.      case 0x090: DIWSTOP(value); break;
  3323.      case 0x092: DDFSTRT(value); break;
  3324.      case 0x094: DDFSTOP(value); break;
  3325.     
  3326.      case 0x096: DMACON(value); break;
  3327.      case 0x09A: INTENA(value); break;
  3328.      case 0x09C: INTREQ(value); break;
  3329.      case 0x09E: ADKCON(value); break;
  3330.     
  3331.      case 0x0A0: AUD0LCH(value); break;
  3332.      case 0x0A2: AUD0LCL(value); break;
  3333.      case 0x0A4: AUD0LEN(value); break;
  3334.      case 0x0A6: AUD0PER(value); break;
  3335.      case 0x0A8: AUD0VOL(value); break;
  3336.     
  3337.      case 0x0B0: AUD1LCH(value); break;
  3338.      case 0x0B2: AUD1LCL(value); break;
  3339.      case 0x0B4: AUD1LEN(value); break;
  3340.      case 0x0B6: AUD1PER(value); break;
  3341.      case 0x0B8: AUD1VOL(value); break;
  3342.     
  3343.      case 0x0C0: AUD2LCH(value); break;
  3344.      case 0x0C2: AUD2LCL(value); break;
  3345.      case 0x0C4: AUD2LEN(value); break;
  3346.      case 0x0C6: AUD2PER(value); break;
  3347.      case 0x0C8: AUD2VOL(value); break;
  3348.     
  3349.      case 0x0D0: AUD3LCH(value); break;
  3350.      case 0x0D2: AUD3LCL(value); break;
  3351.      case 0x0D4: AUD3LEN(value); break;
  3352.      case 0x0D6: AUD3PER(value); break;
  3353.      case 0x0D8: AUD3VOL(value); break;
  3354.     
  3355.      case 0x0E0: BPLPTH(value, 0); break;
  3356.      case 0x0E2: BPLPTL(value, 0); break;
  3357.      case 0x0E4: BPLPTH(value, 1); break;
  3358.      case 0x0E6: BPLPTL(value, 1); break;
  3359.      case 0x0E8: BPLPTH(value, 2); break;
  3360.      case 0x0EA: BPLPTL(value, 2); break;
  3361.      case 0x0EC: BPLPTH(value, 3); break;
  3362.      case 0x0EE: BPLPTL(value, 3); break;
  3363.      case 0x0F0: BPLPTH(value, 4); break;
  3364.      case 0x0F2: BPLPTL(value, 4); break;
  3365.      case 0x0F4: BPLPTH(value, 5); break;
  3366.      case 0x0F6: BPLPTL(value, 5); break;
  3367.     
  3368.      case 0x100: BPLCON0(value); break;
  3369.      case 0x102: BPLCON1(value); break;
  3370.      case 0x104: BPLCON2(value); break;
  3371.      case 0x106: BPLCON3(value); break;
  3372.     
  3373.      case 0x108: BPL1MOD(value); break;
  3374.      case 0x10A: BPL2MOD(value); break;
  3375.  
  3376.      case 0x110: BPL1DAT(value); break;
  3377.      case 0x112: BPL2DAT(value); break;
  3378.      case 0x114: BPL3DAT(value); break;
  3379.      case 0x116: BPL4DAT(value); break;
  3380.      case 0x118: BPL5DAT(value); break;
  3381.      case 0x11A: BPL6DAT(value); break;
  3382.     
  3383.      case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
  3384.      case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
  3385.      case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
  3386.      case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
  3387.      case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
  3388.      case 0x1BC: case 0x1BE: 
  3389.     COLOR(value & 0xFFF, (addr & 0x3E) / 2);
  3390.     break;    
  3391.      case 0x120: case 0x124: case 0x128: case 0x12C: 
  3392.      case 0x130: case 0x134: case 0x138: case 0x13C:
  3393.     SPRxPTH(value, (addr - 0x120) / 4);
  3394.     break;
  3395.      case 0x122: case 0x126: case 0x12A: case 0x12E: 
  3396.      case 0x132: case 0x136: case 0x13A: case 0x13E:
  3397.     SPRxPTL(value, (addr - 0x122) / 4);
  3398.     break;
  3399.      case 0x140: case 0x148: case 0x150: case 0x158: 
  3400.      case 0x160: case 0x168: case 0x170: case 0x178:
  3401.     SPRxPOS(value, (addr - 0x140) / 8);
  3402.     break;
  3403.      case 0x142: case 0x14A: case 0x152: case 0x15A: 
  3404.      case 0x162: case 0x16A: case 0x172: case 0x17A:
  3405.     SPRxCTL(value, (addr - 0x142) / 8);
  3406.     break;
  3407.      case 0x144: case 0x14C: case 0x154: case 0x15C:
  3408.      case 0x164: case 0x16C: case 0x174: case 0x17C:
  3409.     SPRxDATA(value, (addr - 0x144) / 8);
  3410.     break;
  3411.      case 0x146: case 0x14E: case 0x156: case 0x15E: 
  3412.      case 0x166: case 0x16E: case 0x176: case 0x17E:
  3413.     SPRxDATB(value, (addr - 0x146) / 8);
  3414.     break;
  3415.     
  3416.      case 0x36: JOYTEST(value); break;
  3417. #if defined(ECS_AGNUS) || (AGA_CHIPSET == 1)
  3418.      case 0x5A: BLTCON0L(value); break;
  3419.      case 0x5C: BLTSIZV(value); break;
  3420.      case 0x5E: BLTSIZH(value); break;
  3421. #endif
  3422. #if AGA_CHIPSET == 1
  3423.      case 0x10C: BPLCON4(value); break;
  3424. #endif
  3425.     }
  3426. }
  3427.  
  3428. void custom_bput(CPTR addr, UBYTE value)
  3429. {
  3430.     /* Yes, there are programs that do this. The programmers should be shot.
  3431.      * This might actually work sometimes. */
  3432.     UWORD rval = value;
  3433.     CPTR raddr = addr & 0x1FE;
  3434.     if (addr & 1) {
  3435.     rval |= cregs[raddr >> 1] & 0xFF00;
  3436.     } else {
  3437.     rval <<= 8;
  3438.     rval |= cregs[raddr >> 1] & 0xFF;
  3439.     }
  3440.     custom_wput(raddr, rval);
  3441. }
  3442.  
  3443. void custom_lput(CPTR addr, ULONG value)
  3444. {
  3445.     custom_wput(addr & 0xfffe, value >> 16);
  3446.     custom_wput((addr+2) & 0xfffe, (UWORD)value);
  3447. }
  3448.  
  3449.